mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 11:49:17 +00:00
Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f5cf5dac4d | |||
| 5ffe89dec3 | |||
| 191b709ccf | |||
| b3e15d66ea | |||
| b3751d1dcc | |||
| 928d66eb9d | |||
| 72ecf97497 | |||
| aa8773ce73 | |||
| 6f11155914 | |||
| fd5413164a | |||
| 295f2e0a48 | |||
| 13e5672b3f | |||
| a0723227c0 | |||
| 72b2d2482b | |||
| 0c12761601 | |||
| 4ca5c8f1e7 | |||
| 53cdbdded7 | |||
| bed9da4367 | |||
| 1226c2758d | |||
| 8b2e655723 | |||
| 1061484247 | |||
| b4f014855b | |||
| 8b1bdfd39b | |||
| 1f43ec4d66 | |||
| f3f5b22090 | |||
| eb47bcd4b0 | |||
| 87a91bd632 | |||
| d0bd7b1cdc | |||
| dfff00d4cf | |||
| ba5a7e1549 | |||
| b126f397f7 | |||
| afd8e052de | |||
| 52edd47532 | |||
| da5fbf8341 | |||
| 6129aa6818 | |||
| 041639f430 | |||
| 12f79247dd | |||
| a957bc6450 | |||
| fb5b9c5024 | |||
| cb2dfe0a0f | |||
| e2950af1b6 | |||
| 1b70d39984 | |||
| 91d3776403 | |||
| b4748918f5 | |||
| a1d8393060 | |||
| 4a519004f5 | |||
| 8234c6cf50 | |||
| f50a495690 | |||
| 6c2e29122e | |||
| 250683e830 | |||
| 0f04582b42 | |||
| d9de90718d | |||
| e8651b71fd | |||
| ecdd6fb8ec | |||
| 945e993843 | |||
| fdf78ecadb | |||
| fc9b191578 | |||
| 04e5eaf63c | |||
| 494b1582ca | |||
| c33b820e36 | |||
| cfeb0098a6 | |||
| e2bba32a57 | |||
| 1ca6673ee4 | |||
| cb9326e8b6 | |||
| 10be16ad53 | |||
| 0c26642a72 | |||
| 5d76f9125d | |||
| 5b930f4536 | |||
| b118000672 | |||
| 603de5a42e | |||
| 9fe0157293 | |||
| b3d5df8188 | |||
| 00ce6f42d7 | |||
| ec30c54577 | |||
| 1974eb2a39 | |||
| 03a09809ab | |||
| 825f9fda42 | |||
| a41fb8473b | |||
| d2f02e46e0 | |||
| dcff4516b4 | |||
| 651ee3f6c9 | |||
| 7aefc6047b | |||
| 2bca54fd06 | |||
| 3fd8872e5c | |||
| 57efc58c2f | |||
| 40e422682b | |||
| d2b9fc0960 | |||
| f8fdf1ff98 | |||
| 1d198dbd7c | |||
| 2dd780910a | |||
| ed22b56716 | |||
| 7bcef67820 | |||
| 1941577b24 | |||
| 97a189eda5 | |||
| 0759d1cb85 | |||
| 424e9d2f5c | |||
| 794f6997b8 | |||
| 175b6dede2 | |||
| 91bace0a05 | |||
| 7d829ac78d | |||
| caa9585906 | |||
| d0d6427b38 | |||
| 7c5622f682 | |||
| 12e183b45c | |||
| e52dc71857 | |||
| 9041f4cdbc | |||
| 6f503f735f | |||
| 27830e9f8a | |||
| d8c63ce949 | |||
| 33b2854d63 | |||
| acb51d4444 | |||
| 3bc9bb5f9c | |||
| 58d94edac0 | |||
| d76ae5cd1d | |||
| a11d563704 | |||
| 34c55c8482 | |||
| c6fdfccc61 | |||
| e512c0b0de | |||
| 7afd104b7b | |||
| 60511fa602 | |||
| 9b3924cc00 | |||
| 0bf093351f | |||
| 2d164750f1 | |||
| b8d440f547 | |||
| f25ace130c | |||
| 8b17f9e3a2 | |||
| b97cf1fd9d | |||
| 416b3f0273 | |||
| d3c31e9651 | |||
| 8b963c6b82 | |||
| 989d3ba9f0 | |||
| f3e2d3cc11 | |||
| a7b8b5f6ea | |||
| 7f2adbbb13 | |||
| a82e460406 | |||
| a0e990bf2a | |||
| ddc5630244 | |||
| d377e92fb5 | |||
| b8c3f1e8f8 | |||
| a827afab39 | |||
| 61bb568c94 | |||
| 3f4d8c9907 | |||
| f6466c2ca7 | |||
| 609d93118b | |||
| 193ddd6ff9 |
@@ -2,4 +2,4 @@
|
||||
|
||||
# Remove GPOS
|
||||
$BackupPath = "$Env:UserProfile\Desktop\GPO"
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath $BackupPath -BackupDated -LimitProcessing 2 -Verbose
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath $BackupPath -BackupDated -LimitProcessing 2 -Verbose -WhatIf
|
||||
@@ -1,7 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$GPOS = Get-GPOZaurr
|
||||
$GPOS | Format-Table -AutoSize
|
||||
$GPOS | Format-Table -AutoSize *
|
||||
|
||||
$GPOS[0] | Format-List
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$T = Get-GPOZaurrPermission -GPOName 'Default Domain Policy' -Type 'All'
|
||||
$T = Get-GPOZaurrPermission -GPOName 'Default Domain Policy' -Type 'All' -IncludeOwner
|
||||
$T | Format-Table *
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$T = Get-GPOZaurrPermission -Type Unknown -Verbose
|
||||
$T | Format-Table *
|
||||
$T | Out-HtmlView -ScrollX -Filtering -DisablePaging -ScrollY -Online
|
||||
@@ -1,14 +1,14 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# This Example shows how to deal with GPOs that have owner that doesn't exists anymore (deleted userr or diff domain) - EmptyOrUnknown
|
||||
# This Example shows how to deal with GPOs that have owner that doesn't exists anymore (deleted userr or diff domain) - Unknown
|
||||
# And also can fix at the same time NotAdministrative - this basically looks for users/groups that are not Domain Admins or Enterprise Admins
|
||||
# regardless if current user is still Domain Admin or not
|
||||
|
||||
$GPOs = Get-GPOZaurrOwner -IncludeSysvol #-GPOName
|
||||
$GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
|
||||
$GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
|
||||
|
||||
#Set-GPOZaurrOwner -Type Unknown -Verbose #-LimitProcessing 2 -WhatIf
|
||||
Set-GPOZaurrOwner -Type NotAdministrative -Verbose -LimitProcessing 2 -WhatIf
|
||||
Set-GPOZaurrOwner -Type NotAdministrative -Verbose -LimitProcessing 2 -WhatIf
|
||||
#Set-GPOZaurrOwner -Type NotMatching -Verbose -LimitProcessing 2 -WhatIf
|
||||
|
||||
#Set-GPOZaurrOwner -GPOName 'COMPUTERS | Enable Sets' -Verbose -Principal 'przemyslaw.klys' -WhatIf #-SkipSysvol
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
Get-GPOZaurrPermissionConsistency -GPOName 'Default Domain Controllers Policy' -IncludeDomains 'ad.evotec.xyz'
|
||||
|
||||
Repair-GPOZaurrPermissionConsistency -GPOName 'Default Domain Controllers Policy' -IncludeDomains 'ad.evotec.xyz' -Verbose #-WhatIf -Verbose
|
||||
Repair-GPOZaurrPermissionConsistency -GPOName 'Default Domain Controllers Policy' -IncludeDomains 'ad.evotec.xyz' -Verbose -WhatIf
|
||||
@@ -1,5 +1,5 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrPermissionConsistency -Type All | Format-Table
|
||||
Get-GPOZaurrPermissionConsistency -Type All -VerifyInheritance | Format-Table
|
||||
|
||||
Repair-GPOZaurrPermissionConsistency -LimitProcessing 2 -WhatIf -Verbose
|
||||
@@ -1,3 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrSysvol -Verbose | Format-Table
|
||||
Get-GPOZaurrSysvol -Verbose | Format-Table
|
||||
#Get-GPOZaurrSysvol | Out-HtmlView -ScrollX
|
||||
@@ -1,7 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# this allows you to process X amount of orphaned folders/files (good for testing)
|
||||
Remove-GPOZaurrOrphanedSysvolFolders -Verbose -WhatIf -LimitProcessing 2 -IncludeDomains 'ad.evotec.xyz'
|
||||
Remove-GPOZaurrOrphaned -Verbose -WhatIf -IncludeDomains 'ad.evotec.xyz' #-LimitProcessing 2
|
||||
|
||||
# this runs for whole SYSVOL and checks things against GPOS
|
||||
Remove-GPOZaurrOrphanedSysvolFolders -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 #-WhatIf
|
||||
Remove-GPOZaurrOrphaned -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf
|
||||
@@ -1,3 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Remove-GPOZaurrLegacyFiles -Verbose -BackupPath $Env:USERPROFILE\Desktop\BackupADM -BackupDated -RemoveEmptyFolders #-WhatIf #-LimitProcessing 2 -WhatIf
|
||||
Remove-GPOZaurrLegacyFiles -Verbose -BackupPath $Env:USERPROFILE\Desktop\BackupADM1 -BackupDated -RemoveEmptyFolders -WhatIf -LimitProcessing 2
|
||||
@@ -1,10 +0,0 @@
|
||||
Clear-Host
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Get-GPOZaurrSysvol | ForEach-Object {
|
||||
$Path = $_.Path
|
||||
Get-ChildItem -Path $Path -ErrorAction SilentlyContinue -Recurse -ErrorVariable err -File | ForEach-Object {
|
||||
Get-FileMetaData -File $_ -Signature -HashAlgorithm 'SHA256'
|
||||
}
|
||||
}
|
||||
$Output | Format-Table
|
||||
@@ -0,0 +1,6 @@
|
||||
Clear-Host
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Dictionary = Get-GPOZaurrDictionary #-Splitter '; '
|
||||
$Dictionary | Format-Table
|
||||
$Dictionary | Out-HtmlView
|
||||
@@ -1,4 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
#Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport -DeleteExisting
|
||||
Save-GPOZaurrFiles -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExport' #-DeleteExisting
|
||||
Save-GPOZaurrFiles -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportEvotec' -DeleteExisting -Verbose
|
||||
@@ -1,34 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport
|
||||
#$OutputNoTranslation = Invoke-GPOZaurr -GPOPath $Env:UserProfile\Desktop\GPOExport -NoTranslation
|
||||
#$OutputNoTranslation = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' -NoTranslation
|
||||
$OutputNoTranslation | Format-Table *
|
||||
|
||||
<#
|
||||
New-HTML {
|
||||
foreach ($GPOCategory in $OutputNoTranslation.Keys) {
|
||||
New-HTMLTab -Name $GPOCategory {
|
||||
if ($OutputNoTranslation["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $OutputNoTranslation["$GPOCategory"].Keys) {
|
||||
New-HTMLTab -Name $GpoSettings {
|
||||
New-HTMLTable -DataTable $OutputNoTranslation[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
} else {
|
||||
New-HTMLTable -DataTable $OutputNoTranslation[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-NoTranslationFromDisk.html
|
||||
|
||||
#>
|
||||
foreach ($GPOCategory in $OutputNoTranslation.Keys) {
|
||||
if ($OutputNoTranslation["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $OutputNoTranslation["$GPOCategory"].Keys) {
|
||||
ConvertTo-Excel -DataTable $OutputNoTranslation[$GPOCategory][$GpoSettings] -AllProperties -ExcelWorkSheetName $GpoSettings -FilePath $Env:UserProfile\Desktop\Export\$GpoSettings.xlsx -AutoFilter -AutoFit
|
||||
}
|
||||
} else {
|
||||
ConvertTo-Excel -DataTable $OutputNoTranslation[$GPOCategory][$GpoSettings] -AllProperties -ExcelWorkSheetName $GpoSettings -FilePath $Env:UserProfile\Desktop\Export\$GpoSettings.xlsx -AutoFilter -AutoFit
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
#Invoke-GPOZaurr -OutputType Excel, Object, HTML -Open | Format-Table
|
||||
#$Output = Invoke-GPOZaurr -GPOPath $Env:USERPROFILE\Desktop\GPOExport -NoTranslation #| Format-Table
|
||||
#$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTestRegistryCheck' -NoTranslation
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' -NoTranslation -Verbose
|
||||
#$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExport' -NoTranslation #-OutputType HTML, Object -Open #| Format-Table
|
||||
#$Output.Categories | Out-HtmlView
|
||||
#$Output.Categories | Format-Table
|
||||
$Output | Format-Table
|
||||
#$Output.CategoriesFull | Format-Table
|
||||
#$Output.Count
|
||||
|
||||
$Output.Reports | Format-Table
|
||||
#$Output.Reports.Scripts | Format-Table *
|
||||
#$Output.Reports.AccountPolicies | Format-Table *
|
||||
#$Output.Reports.Audit | Format-Table *
|
||||
#$Output.Reports.Autologon | Format-Table *
|
||||
#$Output.Reports.EventLog | Format-Table *
|
||||
#$Output.Reports.SoftwareInstallation | Format-Table *
|
||||
#$Output.Reports.Policies | Format-Table *
|
||||
#Output.Reports.RegistrySettings | Format-Table *
|
||||
#$Output.Reports.SecurityOptions | Format-Table *
|
||||
#$Output.Reports.SystemServices | Format-Table *
|
||||
#$Output.Reports.SystemServicesNT | Format-Table *
|
||||
#$Output.Reports.LocalUsers | Format-Table *
|
||||
#$Output.Reports.LocalGroups | Format-Table *
|
||||
#$Output.Reports.DriveMapping | Format-Table *
|
||||
#$Output.Reports.Printers | Format-Table *
|
||||
$Output.Reports.TaskScheduler | Format-Table *
|
||||
return
|
||||
# This is section that treats 1 GPO as single object - if there are 5 scripts in 1 GPO there's only one value
|
||||
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' -NoTranslation -SingleObject
|
||||
#$Output
|
||||
#$Output.Reports | Format-Table
|
||||
#$Output.Reports.Scripts | Format-Table *
|
||||
#$Output.Reports.SoftwareInstallation | Format-Table *
|
||||
#$Output.Reports.Policies | Format-Table *
|
||||
#$Output.Reports.RegistrySettings | Format-Table *
|
||||
#$Output.Reports.SecurityOptions | Format-Table *
|
||||
#$Output.Reports.SystemServices | Format-Table *
|
||||
#$Output.Reports.SystemServicesNT | Format-Table *
|
||||
#$Output.Reports.LocalUsers | Format-Table *
|
||||
#$Output.Reports.LocalGroups | Format-Table *
|
||||
#$Output.Reports.DriveMapping | Format-Table *
|
||||
$Output.Reports.Printers | Format-Table *
|
||||
@@ -1,20 +1,22 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr #-NoTranslation
|
||||
#$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPODefender'
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExport' -Type WindowsHelloForBusiness
|
||||
$Output | Format-Table
|
||||
$Output.WindowsDefenderExploitGuard | Format-Table
|
||||
$Output.Reports.RegistrySetting | Format-Table
|
||||
|
||||
# Report to Excel of translated reports
|
||||
foreach ($Key in $Output.Keys) {
|
||||
$Output[$Key] | ConvertTo-Excel -FilePath $Env:USERPROFILE\Desktop\GPOAnalysis.xlsx -ExcelWorkSheetName $Key -AutoFilter -AutoFit -FreezeTopRowFirstColumn
|
||||
}
|
||||
|
||||
# Report to HTML of translated reports
|
||||
New-HTML {
|
||||
foreach ($GPOCategory in $Output.Keys) {
|
||||
New-HTMLTab -Name $GPOCategory {
|
||||
if ($Output["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $Output["$GPOCategory"].Keys) {
|
||||
New-HTMLTab -Name $GpoSettings {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
} else {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
New-HTMLTableOption -DataStore JavaScript
|
||||
foreach ($Key in $Output.Keys) {
|
||||
New-HTMLTab -Name $Key {
|
||||
New-HTMLTable -DataTable $Output[$Key] -Filtering -Title $Key
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO.html
|
||||
} -FilePath $Env:USERPROFILE\Desktop\GPOAnalysis.html -ShowHTML -Online
|
||||
@@ -1,20 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr -NoTranslation
|
||||
$Output | Format-Table
|
||||
|
||||
New-HTML {
|
||||
foreach ($GPOCategory in $Output.Keys) {
|
||||
New-HTMLTab -Name $GPOCategory {
|
||||
if ($Output["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $Output["$GPOCategory"].Keys) {
|
||||
New-HTMLTab -Name $GpoSettings {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
} else {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-NoTranslation.html
|
||||
@@ -0,0 +1,8 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# This gets the same thing as earlier examples
|
||||
# with a difference where one entry per gpo and all settings for that GPO is stored under settings property.
|
||||
$Output = Invoke-GPOZaurr -SingleObject -Verbose
|
||||
$Output | Format-Table
|
||||
$Output.Reports.RegistrySettings | Format-Table *
|
||||
$Output.Reports.RegistrySettings[0].Settings | Format-Table *
|
||||
@@ -1,22 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport
|
||||
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' # -NoTranslation
|
||||
$Output | Format-Table *
|
||||
|
||||
New-HTML {
|
||||
foreach ($GPOCategory in $Output.Keys) {
|
||||
New-HTMLTab -Name $GPOCategory {
|
||||
if ($Output["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $Output["$GPOCategory"].Keys) {
|
||||
New-HTMLTab -Name $GpoSettings {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
} else {
|
||||
New-HTMLTable -DataTable $Output[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-FromDisk.html
|
||||
@@ -0,0 +1,15 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExportAudit
|
||||
|
||||
# This will allow you to process offline data more than once
|
||||
# It's useful for when you want to request different types
|
||||
$Output = Invoke-GPOZaurr -GPOPath $ENV:USERPROFILE\Desktop\GPOExportAudit -Extended -Verbose
|
||||
$Output | Format-Table *
|
||||
$Output.Reports | Format-Table
|
||||
|
||||
# Export to Excel
|
||||
foreach ($Key in $Output.Reports.Keys) {
|
||||
$Output.Reports[$Key] | ConvertTo-Excel -FilePath $Env:USERPROFILE\Desktop\GPOAnalysis.xlsx -ExcelWorkSheetName $Key -AutoFilter -AutoFit -FreezeTopRowFirstColumn
|
||||
}
|
||||
Start-Process "$Env:USERPROFILE\Desktop\GPOAnalysis.xlsx"
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr -Verbose -OutputType HTML, Object -Open
|
||||
$Output | Format-Table
|
||||
@@ -0,0 +1,23 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Asses GPO based on exported data
|
||||
$Output = Invoke-GPOZaurr -GPOPath $Env:USERPROFILE\Desktop\GPOExport_2020.10.12 -Verbose -Type RegistrySetting
|
||||
$Output | Format-Table *
|
||||
|
||||
|
||||
# Export to Excel
|
||||
foreach ($Key in $Output.Keys) {
|
||||
$Output[$Key] | ConvertTo-Excel -FilePath $Env:USERPROFILE\Desktop\EFGPOAnalysis.xlsx -ExcelWorkSheetName $Key -AutoFilter -AutoFit -FreezeTopRowFirstColumn
|
||||
}
|
||||
# Show the Excel
|
||||
Start-Process "$Env:USERPROFILE\Desktop\EFGPOAnalysis.xlsx"
|
||||
|
||||
# Show HTML
|
||||
New-HTML {
|
||||
New-HTMLTableOption -DataStore JavaScript
|
||||
foreach ($Key in $Output.Keys) {
|
||||
New-HTMLTab -Name $Key {
|
||||
New-HTMLTable -DataTable $Output[$Key] -Filtering -Title $Key
|
||||
}
|
||||
}
|
||||
} -FilePath $Env:USERPROFILE\Desktop\EFGPOAnalysis.html -ShowHTML -Online
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr -GPOPath $ENV:USERPROFILE\Desktop\GPOTestingUserAccess -Verbose
|
||||
$Output | Format-Table *
|
||||
@@ -1,25 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport
|
||||
|
||||
$OutputTranslation = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExport'
|
||||
$OutputTranslation | Format-Table
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExport' -NoTranslation
|
||||
$Output | Format-Table *
|
||||
|
||||
#$Output.LugsSettings.LocalUsersAndGroups | Format-List *
|
||||
|
||||
$GPOEntry = $Output.LugsSettings.LocalUsersAndGroups[0]
|
||||
|
||||
$CreateGPO = @{}
|
||||
foreach ($User in $GPOEntry.User) {
|
||||
# $User | Format-Table
|
||||
# $User.Properties | Format-Table
|
||||
}
|
||||
|
||||
|
||||
foreach ($Group in $GPOEntry.Group) {
|
||||
#$Group | Format-Table
|
||||
$Group.Properties | Format-Table
|
||||
$Group.Properties.Members | Format-Table
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport
|
||||
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' -NoTranslation
|
||||
$Output | Format-Table *
|
||||
@@ -1,11 +0,0 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# This is purely for building GPO Dictionary, mostly for development needs to help asses what is there
|
||||
|
||||
$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' -NoTranslation
|
||||
#$Output | Format-Table *
|
||||
|
||||
$LookingFor = $Output | Select-GPOTranslation -Category 'SecuritySettings' -Settings 'UserRightsAssignment'
|
||||
$LookingFor | Format-Table
|
||||
$LookingFor.Types | Format-Table
|
||||
#$LookingFor.Data | Format-Table
|
||||
@@ -1,6 +1,6 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Policies = Get-GPOZaurrFilesPolicyDefinitions -Signature
|
||||
$Policies = Get-GPOZaurrFilesPolicyDefinition -Signature
|
||||
$Policies | Format-Table
|
||||
#$Policies.FilesToDelete | Format-Table *
|
||||
$Policies['ad.evotec.xyz'] | Format-Table *
|
||||
@@ -1,5 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrEmptyFolders | Where-Object { $_.Name -eq 'Adm' } | Format-Table *
|
||||
# Report on empty folders
|
||||
Get-GPOZaurrFolders -FolderType Empty | Format-Table *
|
||||
|
||||
Remove-GPOZaurrEmptyFolders -Folders Adm -Verbose -LimitProcessing 1
|
||||
# ! NOT READY FOR EMPTY
|
||||
#Remove-GPOZaurrFolders -FolderType Empty -Verbose -BackupPath $Env:USERPROFILE\Desktop\SomeBackup1 -WhatIf
|
||||
@@ -0,0 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Report on NTFRS folders
|
||||
Get-GPOZaurrFolders -FolderType NTFRS | Format-Table *
|
||||
|
||||
# Remove NTFRS (broken replication folders)
|
||||
Remove-GPOZaurrFolders -FolderType NTFRS -Verbose -BackupPath $Env:USERPROFILE\Desktop\SomeBackup -WhatIf
|
||||
@@ -0,0 +1,10 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Cleanup based on https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/manually-clearing-the-conflictanddeleted-folder-in-dfsr/ba-p/395711
|
||||
|
||||
# Get dfsr information
|
||||
$DFSR = Get-GPOZaurrSysvolDFSR
|
||||
$DFSR | Format-Table *
|
||||
|
||||
# Cleanup DFSR Conflict Path
|
||||
Clear-GPOZaurrSysvolDFSR -WhatIf
|
||||
@@ -0,0 +1,81 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Invoke-GPOZaurrSupport -ComputerName 'ad1.ad.evotec.xyz' -UserName 'EVOTEC\przemyslaw.klys' -Type NativeHTML -ForceGPResult -Verbose
|
||||
|
||||
return
|
||||
#$Support1 = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'przemyslaw.klys' -Type Object
|
||||
#$Support = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'EVOTEC\Administrator' -Type Object
|
||||
#$Support.ComputerResults.ExtensionData
|
||||
|
||||
|
||||
foreach ($GpoType in @('UserResults', 'ComputerResults')) {
|
||||
if ($Support.$GpoType.ExtensionData) {
|
||||
foreach ($Extension in $Support.$GpoType.ExtensionData) {
|
||||
$GPOSettingTypeSplit = ($Extension.type -split ':')
|
||||
#$Extension
|
||||
#$Extension | Get-Member -MemberType Properties -ErrorAction Stop
|
||||
$KeysToLoop = $Extension | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin @($GPOSettingTypeSplit[0], 'xmlns', 'blocked', 'type') }
|
||||
foreach ($GpoSettings in $KeysToLoop.Name) {
|
||||
$Extension.$GpoSettings | Format-Table
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# $env:LOGONSERVER
|
||||
# if($env:LOGONSERVER -match "MicrosoftAccount") {"Logged on with Windows account"}
|
||||
|
||||
# If it reports \\MicrosoftAccount, they are using their Windows account to sign in instead of domain credentials.
|
||||
#You can check this by using the IF statement as shown here:
|
||||
|
||||
|
||||
#[System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name
|
||||
|
||||
#[System.DirectoryServices.ActiveDirectory.DomainController]::
|
||||
|
||||
# https://concurrency.com/blog/may-2018/domain-controller-selection
|
||||
#echo %logonserver% - This shows the DC that was used to authenticate and log in the current user
|
||||
#nltest /dsgetsite - This shows the AD site that the current server has detected that it's in
|
||||
#nltest /dclist: (include the colon at the end) - This shows the list of DCs in the current domain, including which site each is in.
|
||||
# nslookup -type=srv _ldap._tcp.mydomain.local. - This will query the primary DNS server for all domain controller SRV records. This should return all of the DCs in the domain. In this example, MGLABDC4 and MGLABDC5 are returned.
|
||||
# nslookup -type=srv _ldap._tcp.mysitename._sites.dc._msdcs.mydomain.local. - This will query the primary DNS server for domain controllers that are registered in "mysitename". In this example, only MGLABDC4 is in the site that was queried, which matches the information we found with nltest /dclist: previously.
|
||||
|
||||
|
||||
# Windows 10
|
||||
|
||||
#Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
|
||||
#Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
|
||||
#Remove-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
|
||||
|
||||
Write-Output %logonserver%
|
||||
nltest /dsgetsite
|
||||
nltest /dclist:
|
||||
|
||||
$env:LOGONSERVER
|
||||
[System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name
|
||||
nslookup -type=srv _ldap._tcp.ad.colmore.com.
|
||||
nslookup -type=srv _ldap._tcp.birmingham._sites.dc._msdcs.ad.colmore.com.
|
||||
|
||||
|
||||
function Get-PreData {
|
||||
param(
|
||||
|
||||
)
|
||||
[PSCustomObject] @{
|
||||
Site = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ComputerDataInformation {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string] $ComputerName = $Env:COMPUTERNAME
|
||||
)
|
||||
[PSCustomObject] @{
|
||||
Bios = Get-ComputerBios -ComputerName $ComputerName
|
||||
Network = Get-ComputerNetwork -ComputerName $ComputerName
|
||||
NetworkCard = Get-ComputerNetworkCard -ComputerName $ComputerName
|
||||
}
|
||||
}
|
||||
Get-ComputerDataInformation -ComputerName 'AD1.AD.EVOTEC.XYZ'
|
||||
#Get-ComputerNetwork -ComputerName 'AD1.AD.EVOTEC.XYZ' #| Format-Table
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
ConvertFrom-CSExtension -CSE '{FC715823-C5FB-11D1-9EEF-00A0C90347FF}'
|
||||
ConvertFrom-CSExtension -CSE '{A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B}'
|
||||
@@ -0,0 +1,21 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Extracts CSE from registry
|
||||
$AllRegistryExtensions = Find-CSExtension
|
||||
$AllRegistryExtensions | Format-Table
|
||||
|
||||
# Uses Hashtable - similar to above but much faster
|
||||
$AllRegistryExtensionsFaster = foreach ($CSE in $AllRegistryExtensions) {
|
||||
ConvertFrom-CSExtension -CSE $CSE.CSE
|
||||
}
|
||||
$AllRegistryExtensionsFaster | Format-Table
|
||||
|
||||
# With this we can find out if we're missing anything in hashtable so we can update code if nessecary
|
||||
$MissingEntries = foreach ($CSE in $AllRegistryExtensions) {
|
||||
$Output = ConvertFrom-CSExtension -CSE $CSE.CSE
|
||||
if ($Output.CSE -eq $Output.Description) {
|
||||
# THis means the value in hashtable is missing this entry and we should add it
|
||||
$CSE
|
||||
}
|
||||
}
|
||||
$MissingEntries | Format-Table
|
||||
@@ -0,0 +1,10 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Get basic output DN, CanonicalName, BlockInheritance (True/False)
|
||||
#$Objects = Get-GPOZaurrInheritance
|
||||
#$Objects | Format-Table
|
||||
|
||||
# Get same output DN, CanonicalName, BlockInheritance (True/False) + Users/Computers + UsersCount/ComputerCount for those with Blocked Inhertiance
|
||||
# This is so you can have a list what machines are affected
|
||||
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance
|
||||
$Objects | Format-Table
|
||||
@@ -0,0 +1,10 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Default Permissions:
|
||||
# 'GpoApply', 'GpoEdit', 'GPOCustom', 'GpoEditDeleteModifySecurity', 'GPORead'
|
||||
# If you want to see also owners
|
||||
# 'GpoOwner'
|
||||
# If you want to include Root Level Permissions
|
||||
# 'GpoRootCreate', 'GpoRootOwner'
|
||||
$SummaryPermission = Get-GPOZaurrPermissionSummary -IncludePermissionType 'GpoCustom', 'GpoEdit', 'GpoEditDeleteModifySecurity', 'GpoOwner', 'GpoRootCreate', 'GpoRootOwner'
|
||||
$SummaryPermission | Sort-Object -Property Permission | Format-Table
|
||||
@@ -0,0 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrPermissionRoot -Verbose | Format-Table *
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$FilesAll = Get-GPOZaurrNetlogon
|
||||
$FilesAll | Format-Table -a *
|
||||
+20
-15
@@ -1,29 +1,34 @@
|
||||
@{
|
||||
AliasesToExport = 'Find-GPO'
|
||||
AliasesToExport = @('Get-GPOZaurrSysvol', 'Get-GPOZaurrFilesPolicyDefinitions', 'Find-GPO', 'Remove-GPOZaurrOrphaned')
|
||||
Author = 'Przemyslaw Klys'
|
||||
CmdletsToExport = @()
|
||||
CompanyName = 'Evotec'
|
||||
CompatiblePSEditions = 'Desktop'
|
||||
CompatiblePSEditions = @('Desktop')
|
||||
Copyright = '(c) 2011 - 2020 Przemyslaw Klys @ Evotec. All rights reserved.'
|
||||
Description = 'Group Policy Eater is a PowerShell module that aims to gather information about Group Policies but also allows fixing issues that you may find in them.'
|
||||
FunctionsToExport = 'Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrEmptyFolders', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinitions', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrSysvol', 'Get-WMIFilter', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrPermission', 'New-GPOZaurrWMI', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrEmptyFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrOrphanedSysvolFolders', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Select-GPOTranslation', 'Set-GPOOwner', 'Set-GPOZaurrOwner'
|
||||
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrDictionary', 'Get-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-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Show-GPOZaurr')
|
||||
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
|
||||
ModuleVersion = '0.0.49'
|
||||
ModuleVersion = '0.0.66'
|
||||
PowerShellVersion = '5.1'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
Tags = 'Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy'
|
||||
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
|
||||
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
|
||||
ExternalModuleDependencies = 'ActiveDirectory', 'GroupPolicy', 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility'
|
||||
ExternalModuleDependencies = @('CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility')
|
||||
}
|
||||
}
|
||||
RequiredModules = @{
|
||||
ModuleVersion = '0.0.161'
|
||||
ModuleName = 'PSSharedGoods'
|
||||
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.65'
|
||||
ModuleName = 'ADEssentials'
|
||||
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
|
||||
}, 'ActiveDirectory', 'GroupPolicy', 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility'
|
||||
RequiredModules = @(@{
|
||||
ModuleVersion = '0.0.186'
|
||||
ModuleName = 'PSSharedGoods'
|
||||
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.99'
|
||||
ModuleName = 'ADEssentials'
|
||||
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.116'
|
||||
ModuleName = 'PSWriteHTML'
|
||||
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
|
||||
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility')
|
||||
RootModule = 'GPOZaurr.psm1'
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
function ConvertFrom-XMLRSOP {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Xml.XmlElement]$Content,
|
||||
[string] $ResultsType,
|
||||
[Microsoft.GroupPolicy.GPRsop] $ResultantSetPolicy,
|
||||
[string] $Splitter = [System.Environment]::NewLine
|
||||
)
|
||||
$GPOPrimary = [ordered] @{
|
||||
Summary = $null
|
||||
SummaryDetails = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
SummaryDownload = $null
|
||||
ResultantSetPolicy = $ResultantSetPolicy
|
||||
|
||||
GroupPolicies = $null
|
||||
GroupPoliciesLinks = $null
|
||||
GroupPoliciesApplied = $null
|
||||
GroupPoliciesDenied = $null
|
||||
Results = [ordered]@{}
|
||||
}
|
||||
|
||||
$Object = [ordered] @{
|
||||
ReadTime = [DateTime] $Content.ReadTime
|
||||
ComputerName = $Content.$ResultsType.Name
|
||||
DomainName = $Content.$ResultsType.Domain
|
||||
OrganizationalUnit = $Content.$ResultsType.SOM
|
||||
Site = $Content.$ResultsType.Site
|
||||
GPOTypes = $Content.$ResultsType.ExtensionData.Name.'#text' -join $Splitter
|
||||
SlowLink = if ($Content.$ResultsType.SlowLink -eq 'true') { $true } else { $false };
|
||||
}
|
||||
|
||||
$GPOPrimary['Summary'] = $Object
|
||||
[Array] $GPOPrimary['SecurityGroups'] = foreach ($Group in $Content.$ResultsType.SecurityGroup) {
|
||||
[PSCustomObject] @{
|
||||
Name = $Group.Name.'#Text'
|
||||
SID = $Group.SID.'#Text'
|
||||
}
|
||||
}
|
||||
[Array] $GPOPrimary['GroupPolicies'] = foreach ($GPO in $Content.$ResultsType.GPO) {
|
||||
|
||||
<#
|
||||
$EventsReason = @{
|
||||
'NOTAPPLIED-EMPTY' = 'Not Applied (Empty)'
|
||||
'DENIED-WMIFILTER' = 'Denied (WMI Filter)'
|
||||
'DENIED-SECURITY' = 'Denied (Security)'
|
||||
}
|
||||
#>
|
||||
# Lets translate CSE extensions as some didn't translate automatically
|
||||
$ExtensionName = $GPO.ExtensionName | ForEach-Object {
|
||||
ConvertFrom-CSExtension -CSE $_ -Limited
|
||||
}
|
||||
$GPOObject = [PSCustomObject] @{
|
||||
Name = $GPO.Name
|
||||
#Path = $GPO.Path
|
||||
GUID = $GPO.Path.Identifier.'#text'
|
||||
DomainName = if ($GPO.Path.Domain.'#text') { $GPO.Path.Domain.'#text' } else { 'Local Policy' };
|
||||
#VersionDirectory = $GPO.VersionDirectory
|
||||
#VersionSysvol = $GPO.VersionSysvol
|
||||
Revision = -join ('AD (', $GPO.VersionDirectory, '), SYSVOL (', $GPO.VersionSysvol, ')')
|
||||
IsValid = if ($GPO.IsValid -eq 'true') { $true } else { $false };
|
||||
Status = if ($GPO.FilterAllowed -eq 'true' -and $GPO.AccessDenied -eq 'false') { 'Applied' } else { 'Denied' };
|
||||
FilterAllowed = if ($GPO.FilterAllowed -eq 'true') { $true } else { $false };
|
||||
AccessAllowed = if ($GPO.AccessDenied -eq 'true') { $false } else { $true };
|
||||
FilterName = $GPO.FilterName # : Test
|
||||
ExtensionName = ($ExtensionName | Sort-Object -Unique) -join '; '
|
||||
# This isn't really pretty for large amount of links but can be useful for assesing things
|
||||
SOMOrder = $GPO.Link.SOMOrder -join '; '
|
||||
AppliedOrder = $GPO.Link.AppliedOrder -join '; '
|
||||
LinkOrder = $GPO.Link.LinkOrder -join '; '
|
||||
Enabled = ($GPO.Link.Enabled | ForEach-Object { if ($_ -eq 'true') { $true } else { $false }; }) -join '; '
|
||||
Enforced = ($GPO.Link.NoOverride | ForEach-Object { if ($_ -eq 'true') { $true } else { $false }; }) -join '; ' # : true
|
||||
SecurityFilter = $GPO.SecurityFilter -join '; ' # SecurityFilter : {NT AUTHORITY\Authenticated Users, EVOTEC\GDS-TestGroup3}
|
||||
FilterId = $GPO.FilterID # : MSFT_SomFilter.ID="{ff08bc72-dae6-4890-b4cf-85a9c3b00056}",Domain="ad.evotec.xyz"
|
||||
Links = $GPO.Link.SOMPath -join '; '
|
||||
}
|
||||
$GPOObject
|
||||
}
|
||||
[Array] $GPOPrimary['GroupPoliciesLinks'] = foreach ($GPO in $Content.$ResultsType.GPO) {
|
||||
foreach ($Link in $GPO.Link) {
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $GPO.Name
|
||||
DomainName = $GPO.Path.Domain.'#text'
|
||||
GUID = $GPO.Path.Identifier.'#text'
|
||||
SOMPath = $Link.SOMPath # : ad.evotec.xyz
|
||||
SOMOrder = $Link.SOMOrder # : 2
|
||||
AppliedOrder = $Link.AppliedOrder # : 0
|
||||
LinkOrder = $Link.LinkOrder # : 4
|
||||
Enabled = if ($Link.Enabled -eq 'true') { $true } else { $false }; # : true
|
||||
Enforced = if ($Link.NoOverride -eq 'true') { $true } else { $false }; # : true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Array] $GPOPrimary['ScopeOfManagement'] = foreach ($SOM in $Content.$ResultsType.SearchedSOM) {
|
||||
[PSCustomObject] @{
|
||||
Path = $SOM.Path
|
||||
Type = $SOM.Type
|
||||
Order = $SOM.Order
|
||||
BlocksInheritance = if ($SOM.BlocksInheritance -eq 'true') { $true } else { $false };
|
||||
Blocked = if ($SOM.Blocked -eq 'true') { $true } else { $false };
|
||||
Reason = if ($SOM.Reason -eq 'true') { $true } else { $false };
|
||||
}
|
||||
}
|
||||
[Array] $GPOPrimary['ExtensionStatus'] = foreach ($Details in $Content.$ResultsType.ExtensionStatus) {
|
||||
[PSCustomObject] @{
|
||||
Name = $Details.Name # : Registry
|
||||
Identifier = $Details.Identifier # : {35378EAC-683F-11D2-A89A-00C04FBBCFA2}
|
||||
BeginTime = $Details.BeginTime # : 2020-04-02T12:05:10
|
||||
EndTime = $Details.EndTime # : 2020-04-02T12:05:10
|
||||
LoggingStatus = $Details.LoggingStatus # : Complete
|
||||
Error = $Details.Error # : 0
|
||||
}
|
||||
}
|
||||
[Array] $GPOPrimary['ExtensionData'] = $Content.$ResultsType.ExtensionData.Extension
|
||||
|
||||
|
||||
foreach ($Single in $Content.$ResultsType.EventsDetails.SinglePassEventsDetails) {
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"] = [ordered] @{}
|
||||
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['SummaryDetails'] = [Ordered] @{
|
||||
ActivityId = $Single.ActivityId # : {6400d0bf-ac88-4ee6-b2c2-ca2cbbab0695}
|
||||
ProcessingTrigger = $Single.ProcessingTrigger # : Periodic
|
||||
ProcessingAppMode = $Single.ProcessingAppMode # : Background
|
||||
LinkSpeedInKbps = $Single.LinkSpeedInKbps # : 0
|
||||
SlowLinkThresholdInKbps = $Single.SlowLinkThresholdInKbps # : 500
|
||||
DomainControllerName = $Single.DomainControllerName # : AD1.ad.evotec.xyz
|
||||
DomainControllerIPAddress = $Single.DomainControllerIPAddress # : 192.168.240.189
|
||||
PolicyProcessingMode = $Single.PolicyProcessingMode # : None
|
||||
PolicyElapsedTimeInMilliseconds = $Single.PolicyElapsedTimeInMilliseconds # : 1202
|
||||
ErrorCount = $Single.ErrorCount # : 0
|
||||
WarningCount = $Single.WarningCount # : 0
|
||||
}
|
||||
|
||||
$GPOPrimary['SummaryDetails'].Add([PSCustomObject] $GPOPrimary['Results']["$($Single.ActivityId)"]['SummaryDetails'])
|
||||
|
||||
[Array] $GPOPrimary['Results']["$($Single.ActivityId)"]['ProcessingTime'] = foreach ($Details in $Single.ExtensionProcessingTime) {
|
||||
[PSCustomObject] @{
|
||||
ExtensionName = $Details.ExtensionName
|
||||
ExtensionGuid = $Details.ExtensionGuid
|
||||
ElapsedTimeInMilliseconds = $Details.ElapsedTimeInMilliseconds
|
||||
ProcessedTimeStamp = $Details.ProcessedTimeStamp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$EventsLevel = @{
|
||||
'5' = 'Verbose'
|
||||
'4' = 'Informational'
|
||||
'3' = 'Warning'
|
||||
'2' = 'Error'
|
||||
'1' = 'Critical'
|
||||
'0' = 'LogAlways'
|
||||
}
|
||||
$EventsReason = @{
|
||||
'NOTAPPLIED-EMPTY' = 'Not Applied (Empty)'
|
||||
'DENIED-WMIFILTER' = 'Denied (WMI Filter)'
|
||||
'DENIED-SECURITY' = 'Denied (Security)'
|
||||
}
|
||||
|
||||
[Array] $GPOPrimary['Results']["$($Single.ActivityId)"]['Events'] = foreach ($Event in $Single.EventRecord) {
|
||||
[xml] $EventDetails = $Event.EventXML
|
||||
$EventInformation = [ordered] @{
|
||||
Description = $Event.EventDescription
|
||||
Provider = $EventDetails.Event.System.Provider.Name # : Provider
|
||||
ProviderGUID = $EventDetails.Event.System.Provider.Guid
|
||||
EventID = $EventDetails.Event.System.EventID # : 4006
|
||||
Version = $EventDetails.Event.System.Version # : 1
|
||||
Level = $EventsLevel[$EventDetails.Event.System.Level] # : 4
|
||||
Task = $EventDetails.Event.System.Task # : 0
|
||||
Opcode = $EventDetails.Event.System.Opcode # : 1
|
||||
Keywords = $EventDetails.Event.System.Keywords # : 0x4000000000000000
|
||||
TimeCreated = [DateTime] $EventDetails.Event.System.TimeCreated.SystemTime # : TimeCreated, 2020-08-09T20:16:44.5668052Z
|
||||
EventRecordID = $EventDetails.Event.System.EventRecordID # : 10641325
|
||||
Correlation = $EventDetails.Event.System.Correlation.ActivityID # : Correlation
|
||||
Execution = -join ("ProcessID: ", $EventDetails.Event.System.Execution.ProcessID, " ThreadID: ", $EventDetails.Event.System.Execution.ThreadID) # : Execution
|
||||
Channel = $EventDetails.Event.System.Channel # : Microsoft-Windows-GroupPolicy / Operational
|
||||
Computer = $EventDetails.Event.System.Computer # : AD1.ad.evotec.xyz
|
||||
Security = $EventDetails.Event.System.Security.UserID # : Security
|
||||
}
|
||||
foreach ($Entry in $EventDetails.Event.EventData.Data) {
|
||||
$EventInformation["$($Entry.Name)"] = $Entry.'#text'
|
||||
}
|
||||
[PSCustomObject] $EventInformation
|
||||
}
|
||||
|
||||
# Lets build events by ID, this will be useful for better/easier processing
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID'] = [ordered] @{}
|
||||
$GroupedEvents = $GPOPrimary['Results']["$($Single.ActivityId)"]['Events'] | Group-Object -Property EventId
|
||||
foreach ($Events in $GroupedEvents) {
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID'][$Events.Name] = $Events.Group
|
||||
}
|
||||
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['GroupPoliciesApplied'] = & {
|
||||
if ($GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5312']) {
|
||||
[xml] $GPODetailsApplied = -join ('<Details>', $GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5312'].GPOinfoList, '</Details>')
|
||||
foreach ($GPO in $GPODetailsApplied.Details.GPO) {
|
||||
$ReturnObject = [ordered] @{
|
||||
GUID = $GPO.ID # : { 4E1F9C70-1DDB-4AB6-BBA3-14A8E07F0B4B }
|
||||
DisplayName = $GPO.Name # : DC | Event Log Settings
|
||||
Version = $GPO.Version # : 851981
|
||||
Link = $GPO.SOM # : LDAP: / / OU = Domain Controllers, DC = ad, DC = evotec, DC = xyz
|
||||
SysvolPath = $GPO.FSPath # : \\ad.evotec.xyz\SysVol\ad.evotec.xyz\Policies\ { 4E1F9C70-1DDB-4AB6-BBA3-14A8E07F0B4B }\Machine
|
||||
#GPOTypes = $GPO.Extensions -join '; ' # : [ { 35378EAC-683F-11D2-A89A-00C04FBBCFA2 } { D02B1F72 - 3407 - 48AE-BA88-E8213C6761F1 }]
|
||||
}
|
||||
$TranslatedExtensions = foreach ($Extension in $GPO.Extensions) {
|
||||
ConvertFrom-CSExtension -CSE $Extension -Limited
|
||||
}
|
||||
$ReturnObject['GPOTypes'] = $TranslatedExtensions -join '; '
|
||||
[PSCustomObject] $ReturnObject
|
||||
}
|
||||
}
|
||||
}
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['GroupPoliciesDenied'] = & {
|
||||
if ($GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5312']) {
|
||||
[xml] $GPODetailsDenied = -join ('<Details>', $GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5313'].GPOinfoList, '</Details>')
|
||||
foreach ($GPO in $GPODetailsDenied.Details.GPO) {
|
||||
[PSCustomObject] @{
|
||||
GUID = $GPO.ID #: { 6AC1786C-016F-11D2-945F-00C04fB984F9 }
|
||||
DisplayName = $GPO.Name #: Default Domain Controllers Policy
|
||||
Version = $GPO.Version #: 131074
|
||||
Link = $GPO.SOM #: LDAP: / / OU = Domain Controllers, DC = ad, DC = evotec, DC = xyz
|
||||
SysvolPath = $GPO.FSPath #: \\ad.evotec.xyz\sysvol\ad.evotec.xyz\Policies\ { 6AC1786C-016F-11D2-945F-00C04fB984F9 }\Machine
|
||||
Reason = $EventsReason["$($GPO.Reason)"] #: DENIED-WMIFILTER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$GPOPrimary['Results']["$($Single.ActivityId)"]['SummaryDownload'] = & {
|
||||
if ($GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126']) {
|
||||
[PSCustomObject] @{
|
||||
IsBackgroundProcessing = if ($GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126'].IsBackgroundProcessing -eq 'true') { $true } else { $false }; # : true
|
||||
IsAsyncProcessing = if ($GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126'].IsAsyncProcessing -eq 'true') { $true } else { $false }; # : false
|
||||
Downloaded = $GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126'].NumberOfGPOsDownloaded # : 7
|
||||
Applicable = $GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126'].NumberOfGPOsApplicable # : 6
|
||||
DownloadTimeMiliseconds = $GPOPrimary['Results']["$($Single.ActivityId)"]['EventsByID']['5126'].GPODownloadTimeElapsedInMilliseconds # : 375
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
$GPOPrimary
|
||||
}
|
||||
@@ -1,39 +1,95 @@
|
||||
function ConvertTo-XMLAccountPolicy {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
ClearTextPassword = 'Not Set'
|
||||
LockoutBadCount = 'Not Set'
|
||||
LockoutDuration = 'Not Set'
|
||||
MaximumPasswordAge = 'Not Set'
|
||||
MinimumPasswordAge = 'Not Set'
|
||||
MinimumPasswordLength = 'Not Set'
|
||||
PasswordComplexity = 'Not Set'
|
||||
PasswordHistorySize = 'Not Set'
|
||||
ResetLockoutCount = 'Not Set'
|
||||
MaxClockSkew = 'Not Set'
|
||||
MaxRenewAge = 'Not Set'
|
||||
MaxServiceAge = 'Not Set'
|
||||
MaxTicketAge = 'Not Set'
|
||||
TicketValidateClient = 'Not Set'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
if ($GPOEntry.SettingBoolean) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = if ($GPOEntry.SettingBoolean -eq 'true') { 'Enabled' } elseif ($GPOEntry.SettingBoolean -eq 'false') { 'Disabled' } else { 'Not set' };
|
||||
} elseif ($GPOEntry.SettingNumber) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = $GPOEntry.SettingNumber
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = @(
|
||||
$Settings = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
ClearTextPassword = 'Not Set'
|
||||
LockoutBadCount = 'Not Set'
|
||||
LockoutDuration = 'Not Set'
|
||||
MaximumPasswordAge = 'Not Set'
|
||||
MinimumPasswordAge = 'Not Set'
|
||||
MinimumPasswordLength = 'Not Set'
|
||||
PasswordComplexity = 'Not Set'
|
||||
PasswordHistorySize = 'Not Set'
|
||||
ResetLockoutCount = 'Not Set'
|
||||
MaxClockSkew = 'Not Set'
|
||||
MaxRenewAge = 'Not Set'
|
||||
MaxServiceAge = 'Not Set'
|
||||
MaxTicketAge = 'Not Set'
|
||||
TicketValidateClient = 'Not Set'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
if ($GPOEntry.SettingBoolean) {
|
||||
$Settings[$($GPOEntry.Name)] = if ($GPOEntry.SettingBoolean -eq 'true') { 'Enabled' } elseif ($GPOEntry.SettingBoolean -eq 'false') { 'Disabled' } else { 'Not set' };
|
||||
} elseif ($GPOEntry.SettingNumber) {
|
||||
$Settings[$($GPOEntry.Name)] = [int] $GPOEntry.SettingNumber
|
||||
}
|
||||
}
|
||||
[PSCustomObject] $Settings
|
||||
)
|
||||
|
||||
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
|
||||
|
||||
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
ClearTextPassword = 'Not Set'
|
||||
LockoutBadCount = 'Not Set'
|
||||
LockoutDuration = 'Not Set'
|
||||
MaximumPasswordAge = 'Not Set'
|
||||
MinimumPasswordAge = 'Not Set'
|
||||
MinimumPasswordLength = 'Not Set'
|
||||
PasswordComplexity = 'Not Set'
|
||||
PasswordHistorySize = 'Not Set'
|
||||
ResetLockoutCount = 'Not Set'
|
||||
MaxClockSkew = 'Not Set'
|
||||
MaxRenewAge = 'Not Set'
|
||||
MaxServiceAge = 'Not Set'
|
||||
MaxTicketAge = 'Not Set'
|
||||
TicketValidateClient = 'Not Set'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
if ($GPOEntry.SettingBoolean) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = if ($GPOEntry.SettingBoolean -eq 'true') { 'Enabled' } elseif ($GPOEntry.SettingBoolean -eq 'false') { 'Disabled' } else { 'Not set' };
|
||||
} elseif ($GPOEntry.SettingNumber) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = [int] $GPOEntry.SettingNumber
|
||||
}
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
+222
-33
@@ -2,41 +2,230 @@
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $FullObject
|
||||
[switch] $SingleObject
|
||||
)
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
AuditAccountLogon = 'No auditing'
|
||||
AuditAccountManage = 'No auditing'
|
||||
AuditDSAccess = 'No auditing'
|
||||
AuditLogonEvents = 'No auditing'
|
||||
AuditObjectAccess = 'No auditing'
|
||||
AuditPolicyChange = 'No auditing'
|
||||
AuditPrivilegeUse = 'No auditing'
|
||||
AuditProcessTracking = 'No auditing'
|
||||
AuditSystemEvents = 'No auditing'
|
||||
$SettingType = @{
|
||||
'0' = 'No Auditing'
|
||||
'1' = 'Success'
|
||||
'2' = 'Failure'
|
||||
'3' = 'Success, Failure'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
$SuccessAttempts = try { [bool]::Parse($GPOEntry.SuccessAttempts) } catch { $null };
|
||||
$FailureAttempts = try { [bool]::Parse($GPOEntry.FailureAttempts) } catch { $null };
|
||||
if ($SuccessAttempts -and $FailureAttempts) {
|
||||
$Setting = 'Success, Failure'
|
||||
} elseif ($SuccessAttempts) {
|
||||
$Setting = 'Success'
|
||||
} elseif ($FailureAttempts) {
|
||||
$Setting = 'Failure'
|
||||
} else {
|
||||
$Setting = 'No auditing'
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
$CreateGPO["$($GPOEntry.Name)"] = $Setting
|
||||
[Array] $CreateGPO['Settings'] = @(
|
||||
$Settings = [ordered]@{
|
||||
AuditAccountLogon = 'Not configured'
|
||||
AuditAccountManage = 'Not configured'
|
||||
AuditDSAccess = 'Not configured'
|
||||
AuditLogonEvents = 'Not configured'
|
||||
AuditObjectAccess = 'Not configured'
|
||||
AuditPolicyChange = 'Not configured'
|
||||
AuditPrivilegeUse = 'Not configured'
|
||||
AuditProcessTracking = 'Not configured'
|
||||
AuditSystemEvents = 'Not configured'
|
||||
# Advanced Policies
|
||||
AuditAccountLockout = 'Not configured'
|
||||
AuditApplicationGenerated = 'Not configured'
|
||||
AuditApplicationGroupManagement = 'Not configured'
|
||||
AuditAuditPolicyChange = 'Not configured'
|
||||
AuditAuthenticationPolicyChange = 'Not configured'
|
||||
AuditAuthorizationPolicyChange = 'Not configured'
|
||||
AuditCentralAccessPolicyStaging = 'Not configured'
|
||||
AuditCertificationServices = 'Not configured'
|
||||
AuditComputerAccountManagement = 'Not configured'
|
||||
AuditCredentialValidation = 'Not configured'
|
||||
AuditDetailedDirectoryServiceReplication = 'Not configured'
|
||||
AuditDetailedFileShare = 'Not configured'
|
||||
AuditDirectoryServiceAccess = 'Not configured'
|
||||
AuditDirectoryServiceChanges = 'Not configured'
|
||||
AuditDirectoryServiceReplication = 'Not configured'
|
||||
AuditDistributionGroupManagement = 'Not configured'
|
||||
AuditDPAPIActivity = 'Not configured'
|
||||
AuditFileShare = 'Not configured'
|
||||
AuditFileSystem = 'Not configured'
|
||||
AuditFilteringPlatformConnection = 'Not configured'
|
||||
AuditFilteringPlatformPacketDrop = 'Not configured'
|
||||
AuditFilteringPlatformPolicyChange = 'Not configured'
|
||||
AuditGroupMembership = 'Not configured'
|
||||
AuditHandleManipulation = 'Not configured'
|
||||
AuditIPsecDriver = 'Not configured'
|
||||
AuditIPsecExtendedMode = 'Not configured'
|
||||
AuditIPsecMainMode = 'Not configured'
|
||||
AuditIPsecQuickMode = 'Not configured'
|
||||
AuditKerberosAuthenticationService = 'Not configured'
|
||||
AuditKerberosServiceTicketOperations = 'Not configured'
|
||||
AuditKernelObject = 'Not configured'
|
||||
AuditLogoff = 'Not configured'
|
||||
AuditLogon = 'Not configured'
|
||||
AuditMPSSVCRuleLevelPolicyChange = 'Not configured'
|
||||
AuditNetworkPolicyServer = 'Not configured'
|
||||
AuditNonSensitivePrivilegeUse = 'Not configured'
|
||||
AuditOtherAccountLogonEvents = 'Not configured'
|
||||
AuditOtherAccountManagementEvents = 'Not configured'
|
||||
AuditOtherLogonLogoffEvents = 'Not configured'
|
||||
AuditOtherObjectAccessEvents = 'Not configured'
|
||||
AuditOtherPolicyChangeEvents = 'Not configured'
|
||||
AuditOtherPrivilegeUseEvents = 'Not configured'
|
||||
AuditOtherSystemEvents = 'Not configured'
|
||||
AuditPNPActivity = 'Not configured'
|
||||
AuditProcessCreation = 'Not configured'
|
||||
AuditProcessTermination = 'Not configured'
|
||||
AuditRegistry = 'Not configured'
|
||||
AuditRemovableStorage = 'Not configured'
|
||||
AuditRPCEvents = 'Not configured'
|
||||
AuditSAM = 'Not configured'
|
||||
AuditSecurityGroupManagement = 'Not configured'
|
||||
AuditSecurityStateChange = 'Not configured'
|
||||
AuditSecuritySystemExtension = 'Not configured'
|
||||
AuditSensitivePrivilegeUse = 'Not configured'
|
||||
AuditSpecialLogon = 'Not configured'
|
||||
AuditSystemIntegrity = 'Not configured'
|
||||
AuditUserDeviceClaims = 'Not configured'
|
||||
AuditUserAccountManagement = 'Not configured'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
if ($GPOEntry.PolicyTarget) {
|
||||
# Category = 'AuditSettings', Settings = 'AuditSetting'
|
||||
$Category = $GPOEntry.SubcategoryName -replace ' ', '' -replace '-', '' -replace '/', ''
|
||||
if ($Settings["$($Category)"]) {
|
||||
$Settings["$($Category)"] = $SettingType["$($GPOEntry.SettingValue)"]
|
||||
}
|
||||
} else {
|
||||
# Category = 'SecuritySettings', Settings = 'Audit'
|
||||
$SuccessAttempts = try { [bool]::Parse($GPOEntry.SuccessAttempts) } catch { $null };
|
||||
$FailureAttempts = try { [bool]::Parse($GPOEntry.FailureAttempts) } catch { $null };
|
||||
if ($SuccessAttempts -and $FailureAttempts) {
|
||||
$Setting = 'Success, Failure'
|
||||
} elseif ($SuccessAttempts) {
|
||||
$Setting = 'Success'
|
||||
} elseif ($FailureAttempts) {
|
||||
$Setting = 'Failure'
|
||||
} else {
|
||||
$Setting = 'Not configured'
|
||||
}
|
||||
$Settings["$($GPOEntry.Name)"] = $Setting
|
||||
}
|
||||
}
|
||||
[PSCustomObject] $Settings
|
||||
)
|
||||
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
AuditAccountLogon = 'Not configured'
|
||||
AuditAccountManage = 'Not configured'
|
||||
AuditDSAccess = 'Not configured'
|
||||
AuditLogonEvents = 'Not configured'
|
||||
AuditObjectAccess = 'Not configured'
|
||||
AuditPolicyChange = 'Not configured'
|
||||
AuditPrivilegeUse = 'Not configured'
|
||||
AuditProcessTracking = 'Not configured'
|
||||
AuditSystemEvents = 'Not configured'
|
||||
# Advanced Policies
|
||||
AuditAccountLockout = 'Not configured'
|
||||
AuditApplicationGenerated = 'Not configured'
|
||||
AuditApplicationGroupManagement = 'Not configured'
|
||||
AuditAuditPolicyChange = 'Not configured'
|
||||
AuditAuthenticationPolicyChange = 'Not configured'
|
||||
AuditAuthorizationPolicyChange = 'Not configured'
|
||||
AuditCentralAccessPolicyStaging = 'Not configured'
|
||||
AuditCertificationServices = 'Not configured'
|
||||
AuditComputerAccountManagement = 'Not configured'
|
||||
AuditCredentialValidation = 'Not configured'
|
||||
AuditDetailedDirectoryServiceReplication = 'Not configured'
|
||||
AuditDetailedFileShare = 'Not configured'
|
||||
AuditDirectoryServiceAccess = 'Not configured'
|
||||
AuditDirectoryServiceChanges = 'Not configured'
|
||||
AuditDirectoryServiceReplication = 'Not configured'
|
||||
AuditDistributionGroupManagement = 'Not configured'
|
||||
AuditDPAPIActivity = 'Not configured'
|
||||
AuditFileShare = 'Not configured'
|
||||
AuditFileSystem = 'Not configured'
|
||||
AuditFilteringPlatformConnection = 'Not configured'
|
||||
AuditFilteringPlatformPacketDrop = 'Not configured'
|
||||
AuditFilteringPlatformPolicyChange = 'Not configured'
|
||||
AuditGroupMembership = 'Not configured'
|
||||
AuditHandleManipulation = 'Not configured'
|
||||
AuditIPsecDriver = 'Not configured'
|
||||
AuditIPsecExtendedMode = 'Not configured'
|
||||
AuditIPsecMainMode = 'Not configured'
|
||||
AuditIPsecQuickMode = 'Not configured'
|
||||
AuditKerberosAuthenticationService = 'Not configured'
|
||||
AuditKerberosServiceTicketOperations = 'Not configured'
|
||||
AuditKernelObject = 'Not configured'
|
||||
AuditLogoff = 'Not configured'
|
||||
AuditLogon = 'Not configured'
|
||||
AuditMPSSVCRuleLevelPolicyChange = 'Not configured'
|
||||
AuditNetworkPolicyServer = 'Not configured'
|
||||
AuditNonSensitivePrivilegeUse = 'Not configured'
|
||||
AuditOtherAccountLogonEvents = 'Not configured'
|
||||
AuditOtherAccountManagementEvents = 'Not configured'
|
||||
AuditOtherLogonLogoffEvents = 'Not configured'
|
||||
AuditOtherObjectAccessEvents = 'Not configured'
|
||||
AuditOtherPolicyChangeEvents = 'Not configured'
|
||||
AuditOtherPrivilegeUseEvents = 'Not configured'
|
||||
AuditOtherSystemEvents = 'Not configured'
|
||||
AuditPNPActivity = 'Not configured'
|
||||
AuditProcessCreation = 'Not configured'
|
||||
AuditProcessTermination = 'Not configured'
|
||||
AuditRegistry = 'Not configured'
|
||||
AuditRemovableStorage = 'Not configured'
|
||||
AuditRPCEvents = 'Not configured'
|
||||
AuditSAM = 'Not configured'
|
||||
AuditSecurityGroupManagement = 'Not configured'
|
||||
AuditSecurityStateChange = 'Not configured'
|
||||
AuditSecuritySystemExtension = 'Not configured'
|
||||
AuditSensitivePrivilegeUse = 'Not configured'
|
||||
AuditSpecialLogon = 'Not configured'
|
||||
AuditSystemIntegrity = 'Not configured'
|
||||
AuditUserDeviceClaims = 'Not configured'
|
||||
AuditUserAccountManagement = 'Not configured'
|
||||
}
|
||||
foreach ($GPOEntry in $GPO.DataSet) {
|
||||
if ($GPOEntry.PolicyTarget) {
|
||||
# Category = 'AuditSettings', Settings = 'AuditSetting'
|
||||
$Category = $GPOEntry.SubcategoryName -replace ' ', '' -replace '-', '' -replace '/', ''
|
||||
if ($CreateGPO["$($Category)"]) {
|
||||
$CreateGPO["$($Category)"] = $SettingType["$($GPOEntry.SettingValue)"]
|
||||
}
|
||||
} else {
|
||||
# Category = 'SecuritySettings', Settings = 'Audit'
|
||||
$SuccessAttempts = try { [bool]::Parse($GPOEntry.SuccessAttempts) } catch { $null };
|
||||
$FailureAttempts = try { [bool]::Parse($GPOEntry.FailureAttempts) } catch { $null };
|
||||
if ($SuccessAttempts -and $FailureAttempts) {
|
||||
$Setting = 'Success, Failure'
|
||||
} elseif ($SuccessAttempts) {
|
||||
$Setting = 'Success'
|
||||
} elseif ($FailureAttempts) {
|
||||
$Setting = 'Failure'
|
||||
} else {
|
||||
$Setting = 'Not configured'
|
||||
}
|
||||
$CreateGPO["$($GPOEntry.Name)"] = $Setting
|
||||
}
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
function ConvertTo-XMLGenericPolicy {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[string[]] $Category,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
$UsedNames = [System.Collections.Generic.List[string]]::new()
|
||||
[Array] $Policies = foreach ($Cat in $Category) {
|
||||
$GPO.DataSet | Where-Object { $_.Category -like $Cat }
|
||||
}
|
||||
if ($Policies.Count -gt 0) {
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
|
||||
[Array] $CreateGPO['Settings'] = @(
|
||||
$Settings = [ordered] @{}
|
||||
foreach ($Policy in $Policies) {
|
||||
#if ($Policy.Category -notlike $Category) {
|
||||
# We check again for Category because one GPO can have multiple categories
|
||||
# First check checks GPO globally,
|
||||
# continue
|
||||
#}
|
||||
|
||||
$Name = Format-ToTitleCase -Text $Policy.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$Settings[$Name] = $Policy.State
|
||||
|
||||
foreach ($Setting in @('DropDownList', 'Numeric', 'EditText', 'Text', 'CheckBox', 'ListBox')) {
|
||||
if ($Policy.$Setting) {
|
||||
foreach ($Value in $Policy.$Setting) {
|
||||
if ($Value.Name) {
|
||||
$SubName = Format-ToTitleCase -Text $Value.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$SubName = -join ($Name, $SubName)
|
||||
if ($SubName -notin $UsedNames) {
|
||||
$UsedNames.Add($SubName)
|
||||
} else {
|
||||
$TimesUsed = $UsedNames | Group-Object | Where-Object { $_.Name -eq $SubName }
|
||||
$NumberToUse = $TimesUsed.Count + 1
|
||||
# We add same name 2nd and 3rd time to make sure we count properly
|
||||
$UsedNames.Add($SubName)
|
||||
# We now build property name based on amnount of times
|
||||
$SubName = -join ($SubName, "$NumberToUse")
|
||||
}
|
||||
if ($Value.Value -is [string]) {
|
||||
$Settings["$SubName"] = $Value.Value
|
||||
} elseif ($Value.Value -is [System.Xml.XmlElement]) {
|
||||
|
||||
<#
|
||||
if ($null -eq $Value.Value.Name) {
|
||||
# Shouldn't happen but lets see
|
||||
Write-Verbose $Value
|
||||
} else {
|
||||
$CreateGPO["$SubName"] = $Value.Value.Name
|
||||
}
|
||||
|
||||
#>
|
||||
if ($Value.Value.Element) {
|
||||
$Settings["$SubName"] = $Value.Value.Element.Data -join '; '
|
||||
} elseif ($null -eq $Value.Value.Name) {
|
||||
# Shouldn't happen but lets see
|
||||
Write-Verbose "Tracking $Value"
|
||||
} else {
|
||||
$Settings["$SubName"] = $Value.Value.Name
|
||||
}
|
||||
|
||||
} elseif ($Value.State) {
|
||||
$Settings["$SubName"] = $Value.State
|
||||
} elseif ($null -eq $Value.Value) {
|
||||
# This is most likely Setting 'Text
|
||||
# Do nothing, usually it's just a text to display
|
||||
#Write-Verbose "Skipping value for display because it's empty. Name: $($Value.Name)"
|
||||
} else {
|
||||
# shouldn't happen
|
||||
Write-Verbose $Value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
[PSCustomObject] $Settings
|
||||
)
|
||||
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
}
|
||||
foreach ($Policy in $Policies) {
|
||||
#if ($Policy.Category -notlike $Category) {
|
||||
# We check again for Category because one GPO can have multiple categories
|
||||
# First check checks GPO globally,
|
||||
# continue
|
||||
#}
|
||||
$Name = Format-ToTitleCase -Text $Policy.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$CreateGPO[$Name] = $Policy.State
|
||||
|
||||
foreach ($Setting in @('DropDownList', 'Numeric', 'EditText', 'Text', 'CheckBox', 'ListBox')) {
|
||||
if ($Policy.$Setting) {
|
||||
foreach ($Value in $Policy.$Setting) {
|
||||
if ($Value.Name) {
|
||||
$SubName = Format-ToTitleCase -Text $Value.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$SubName = -join ($Name, $SubName)
|
||||
if ($SubName -notin $UsedNames) {
|
||||
$UsedNames.Add($SubName)
|
||||
} else {
|
||||
$TimesUsed = $UsedNames | Group-Object | Where-Object { $_.Name -eq $SubName }
|
||||
$NumberToUse = $TimesUsed.Count + 1
|
||||
# We add same name 2nd and 3rd time to make sure we count properly
|
||||
$UsedNames.Add($SubName)
|
||||
# We now build property name based on amnount of times
|
||||
$SubName = -join ($SubName, "$NumberToUse")
|
||||
}
|
||||
if ($Value.Value -is [string]) {
|
||||
$CreateGPO["$SubName"] = $Value.Value
|
||||
} elseif ($Value.Value -is [System.Xml.XmlElement]) {
|
||||
|
||||
<#
|
||||
if ($null -eq $Value.Value.Name) {
|
||||
# Shouldn't happen but lets see
|
||||
Write-Verbose $Value
|
||||
} else {
|
||||
$CreateGPO["$SubName"] = $Value.Value.Name
|
||||
}
|
||||
|
||||
#>
|
||||
if ($Value.Value.Element) {
|
||||
$CreateGPO["$SubName"] = $Value.Value.Element.Data -join '; '
|
||||
} elseif ($null -eq $Value.Value.Name) {
|
||||
# Shouldn't happen but lets see
|
||||
Write-Verbose "Tracking $Value"
|
||||
} else {
|
||||
$CreateGPO["$SubName"] = $Value.Value.Name
|
||||
}
|
||||
|
||||
} elseif ($Value.State) {
|
||||
$CreateGPO["$SubName"] = $Value.State
|
||||
} elseif ($null -eq $Value.Value) {
|
||||
# This is most likely Setting 'Text
|
||||
# Do nothing, usually it's just a text to display
|
||||
#Write-Verbose "Skipping value for display because it's empty. Name: $($Value.Name)"
|
||||
} else {
|
||||
# shouldn't happen
|
||||
Write-Verbose $Value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
#}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
function ConvertTo-XMLGenericPublicKey {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[string[]] $Category,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
$SkipNames = ('Name', 'LocalName', 'NamespaceURI', 'Prefix', 'NodeType', 'ParentNode', 'OwnerDocument', 'IsEmpty', 'Attributes', 'HasAttributes', 'SchemaInfo', 'InnerXml', 'InnerText', 'NextSibling', 'PreviousSibling', 'ChildNodes', 'FirstChild', 'LastChild', 'HasChildNodes', 'IsReadOnly', 'OuterXml', 'BaseURI', 'PreviousText')
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Setting in $GPO.DataSet) {
|
||||
$SettingName = $Setting.Name -split ":"
|
||||
$MySettings = [ordered] @{
|
||||
CreatedTime = $GPO.CreatedTime # : 06.06.2020 18:03:36
|
||||
ModifiedTime = $GPO.ModifiedTime # : 17.06.2020 16:08:10
|
||||
ReadTime = $GPO.ReadTime # : 13.08.2020 10:15:37
|
||||
SecurityDescriptor = $GPO.SecurityDescriptor # : SecurityDescriptor
|
||||
FilterDataAvailable = $GPO.FilterDataAvailable # : True
|
||||
}
|
||||
$Name = $SettingName[1]
|
||||
#$Name = Format-ToTitleCase -Text $Setting.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$MySettings['Name'] = $Name # $Setting.Name
|
||||
|
||||
ConvertTo-XMLNested -CreateGPO $MySettings -Setting $Setting -SkipNames $SkipNames #-Name $Name
|
||||
[PSCustomObject] $MySettings
|
||||
}
|
||||
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Setting in $GPO.DataSet) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
}
|
||||
$SettingName = $Setting.Name -split ":"
|
||||
$CreateGPO['CreatedTime'] = $GPO.CreatedTime # : 06.06.2020 18:03:36
|
||||
$CreateGPO['ModifiedTime'] = $GPO.ModifiedTime # : 17.06.2020 16:08:10
|
||||
$CreateGPO['ReadTime'] = $GPO.ReadTime # : 13.08.2020 10:15:37
|
||||
$CreateGPO['SecurityDescriptor'] = $GPO.SecurityDescriptor # : SecurityDescriptor
|
||||
$CreateGPO['FilterDataAvailable'] = $GPO.FilterDataAvailable # : True
|
||||
|
||||
$Name = $SettingName[1]
|
||||
#$Name = Format-ToTitleCase -Text $Setting.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$CreateGPO['Name'] = $Name # $Setting.Name
|
||||
#$CreateGPO['GPOSettingOrder'] = $Setting.GPOSettingOrder
|
||||
|
||||
#foreach ($Property in ($Setting.Properties | Get-Member -MemberType Properties).Name) {
|
||||
|
||||
ConvertTo-XMLNested -CreateGPO $CreateGPO -Setting $Setting -SkipNames $SkipNames #-Name $Name
|
||||
<#
|
||||
$Properties = $Setting.PSObject.Properties.Name | Where-Object { $_ -notin $SkipNames }
|
||||
foreach ($Property in $Properties) {
|
||||
If ($Property -eq 'Value') {
|
||||
if ($Setting.$Property) {
|
||||
#$SubProperties = $Setting.$Property.PSObject.Properties.Name
|
||||
if ($Setting.$Property.Name) {
|
||||
$Name = $Setting.$Property.Name
|
||||
} else {
|
||||
$Name = 'Value'
|
||||
}
|
||||
if ($Setting.$Property.Number) {
|
||||
$CreateGPO[$Name] = $Setting.$Property.Number
|
||||
} elseif ($Setting.$Property.String) {
|
||||
$CreateGPO[$Name] = $Setting.$Property.String
|
||||
} else {
|
||||
throw
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$Name = Format-CamelCaseToDisplayName -Text $Property #-RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
if ($Setting.$Property -is [System.Xml.XmlElement]) {
|
||||
$SubPropeties = $Setting.$Property.PSObject.Properties.Name | Where-Object { $_ -notin $SkipNames }
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
$CreateGPO[$Name] = $Setting.$Property
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
$CreateGPO['Filters'] = $Setting.Filters
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
function ConvertTo-XMLGenericSecuritySettings {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[string[]] $Category
|
||||
)
|
||||
$SkipNames = ('Name', 'LocalName', 'NamespaceURI', 'Prefix', 'NodeType', 'ParentNode', 'OwnerDocument', 'IsEmpty', 'Attributes', 'HasAttributes', 'SchemaInfo', 'InnerXml', 'InnerText', 'NextSibling', 'PreviousSibling', 'Value', 'ChildNodes', 'FirstChild', 'LastChild', 'HasChildNodes', 'IsReadOnly', 'OuterXml', 'BaseURI', 'PreviousText')
|
||||
#$UsedNames = [System.Collections.Generic.List[string]]::new()
|
||||
[Array] $Settings = foreach ($Cat in $Category) {
|
||||
$GPO.DataSet | Where-Object { $null -ne $_.$Cat }
|
||||
}
|
||||
|
||||
if ($Settings.Count -gt 0) {
|
||||
foreach ($Cat in $Category) {
|
||||
foreach ($Setting in $Settings.$Cat) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
}
|
||||
#$Name = Format-ToTitleCase -Text $Setting.Name -RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$CreateGPO['Name'] = $Setting.Name
|
||||
$CreateGPO['GPOSettingOrder'] = $Setting.GPOSettingOrder
|
||||
#foreach ($Property in ($Setting.Properties | Get-Member -MemberType Properties).Name) {
|
||||
|
||||
$Properties = $Setting.Properties.PSObject.Properties.Name | Where-Object { $_ -notin $SkipNames }
|
||||
foreach ($Property in $Properties) {
|
||||
|
||||
$Name = Format-CamelCaseToDisplayName -Text $Property #-RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
$CreateGPO[$Name] = $Setting.Properties.$Property
|
||||
}
|
||||
$CreateGPO['Filters'] = $Setting.Filters
|
||||
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
function ConvertTo-XMLNested {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Collections.IDictionary] $CreateGPO,
|
||||
[System.Xml.XmlElement] $Setting,
|
||||
[string[]] $SkipNames,
|
||||
[string] $Name
|
||||
)
|
||||
|
||||
$Properties = $Setting.PSObject.Properties.Name | Where-Object { $_ -notin $SkipNames }
|
||||
$TempName = $Name
|
||||
foreach ($Property in $Properties) {
|
||||
If ($Property -eq 'Value') {
|
||||
if ($Setting.$Property) {
|
||||
#$SubProperties = $Setting.$Property.PSObject.Properties.Name
|
||||
if ($Setting.$Property.Name) {
|
||||
$Name = $Setting.$Property.Name
|
||||
} else {
|
||||
if (-not $Name) {
|
||||
$Name = 'Value'
|
||||
}
|
||||
}
|
||||
if ($Setting.$Property.Number) {
|
||||
$CreateGPO[$Name] = $Setting.$Property.Number
|
||||
} elseif ($Setting.$Property.String) {
|
||||
$CreateGPO[$Name] = $Setting.$Property.String
|
||||
} else {
|
||||
$CreateGPO[$Name] = $Setting.$Property
|
||||
|
||||
#throw
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$Name = -join ($Name, $Property)
|
||||
$Name = Format-CamelCaseToDisplayName -Text $Name #-RemoveWhiteSpace -RemoveChar ',', '-', "'", '\(', '\)', ':'
|
||||
if ($Setting.$Property -is [System.Xml.XmlElement]) {
|
||||
#$SubPropeties = $Setting.$Property.PSObject.Properties.Name | Where-Object { $_ -notin $SkipNames }
|
||||
|
||||
|
||||
ConvertTo-XMLNested -Setting $Setting.$Property -CreateGPO $CreateGPO -Name $Name -SkipNames $SkipNames
|
||||
|
||||
|
||||
} else {
|
||||
$CreateGPO[$Name] = $Setting.$Property
|
||||
}
|
||||
}
|
||||
$Name = $TempName
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ function ConvertTo-XMLPrinterInternal {
|
||||
$CreateGPO = [ordered]@{
|
||||
Changed = try { [DateTime] $Entry.changed } catch { $Entry.Changed };
|
||||
#uid = $Entry.uid
|
||||
BypassErrors = if ($Entry.bypassErrors -eq '1') { $true } elseif ($Entry.bypassErrors -eq '0') { $false } else { $Entry.bypassErrors };
|
||||
BypassErrors = if ($Entry.bypassErrors -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = $Entry.GPOSettingOrder
|
||||
Filter = $Entry.Filter
|
||||
type = $Type
|
||||
@@ -54,7 +54,7 @@ function ConvertTo-XMLPrinterInternal {
|
||||
GpoSettings = $GPO.GpoSettings
|
||||
Changed = try { [DateTime] $Entry.changed } catch { $Entry.Changed };
|
||||
#uid = $Entry.uid
|
||||
BypassErrors = if ($Entry.bypassErrors -eq '1') { $true } elseif ($Entry.bypassErrors -eq '0') { $false } else { $Entry.bypassErrors };
|
||||
BypassErrors = if ($Entry.bypassErrors -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = $Entry.GPOSettingOrder
|
||||
Filter = $Entry.Filter
|
||||
type = $Type
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
$null -ne $CreateGPO['DefaultUserName'] -or
|
||||
$null -ne $CreateGPO['DefaultPassword']
|
||||
) {
|
||||
$CreateGPO['Linked'] = $GPOEntry.Linked #: True
|
||||
$CreateGPO['LinksCount'] = $GPOEntry.LinksCount #: 1
|
||||
$CreateGPO['Links'] = $GPOEntry.Links #: area1.local
|
||||
$CreateGPO['Linked'] = $GPOEntry.Linked
|
||||
$CreateGPO['LinksCount'] = $GPOEntry.LinksCount
|
||||
$CreateGPO['Links'] = $GPOEntry.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
function ConvertTo-XMLRegistryAutologonOnReport {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO
|
||||
)
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
AutoAdminLogon = $null
|
||||
DefaultDomainName = $null
|
||||
DefaultUserName = $null
|
||||
DefaultPassword = $null
|
||||
DateChangedAutoAdminLogon = $null
|
||||
DateChangedDefaultDomainName = $null
|
||||
DateChangedDefaultUserName = $null
|
||||
DateChangedDefaultPassword = $null
|
||||
}
|
||||
foreach ($Registry in $GPO.Settings) {
|
||||
if ($Registry.Key -eq 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon') {
|
||||
if ($Registry.Name -eq 'AutoAdminLogon') {
|
||||
$CreateGPO['AutoAdminLogon'] = [bool] $Registry.value
|
||||
$CreateGPO['DateChangedAutoAdminLogon'] = [DateTime] $Registry.changed
|
||||
} elseif ($Registry.Name -eq 'DefaultDomainName') {
|
||||
$CreateGPO['DefaultDomainName'] = $Registry.value
|
||||
$CreateGPO['DateChangedDefaultDomainName'] = [DateTime] $Registry.changed
|
||||
} elseif ($Registry.Name -eq 'DefaultUserName') {
|
||||
$CreateGPO['DefaultUserName'] = $Registry.value
|
||||
$CreateGPO['DateChangedDefaultUserName'] = [DateTime] $Registry.changed
|
||||
} elseif ($Registry.Name -eq 'DefaultPassword') {
|
||||
$CreateGPO['DefaultPassword'] = $Registry.value
|
||||
$CreateGPO['DateChangedDefaultPassword'] = [DateTime] $Registry.changed
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($null -ne $CreateGPO['AutoAdminLogon'] -or
|
||||
$null -ne $CreateGPO['DefaultDomainName'] -or
|
||||
$null -ne $CreateGPO['DefaultUserName'] -or
|
||||
$null -ne $CreateGPO['DefaultPassword']
|
||||
) {
|
||||
$CreateGPO['Linked'] = $GPO.Linked #: True
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount #: 1
|
||||
$CreateGPO['Links'] = $GPO.Links #: area1.local
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
function ConvertTo-XMLRegistryInternetExplorerZones {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO
|
||||
)
|
||||
foreach ($Registry in $GPO.Settings) {
|
||||
$Keys = @(
|
||||
'Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\'
|
||||
'Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\EscDomains\'
|
||||
)
|
||||
$Found = $false
|
||||
foreach ($Key in $Keys) {
|
||||
if ($Registry.Key -like "$Key*") {
|
||||
$Found = $true
|
||||
}
|
||||
}
|
||||
if ($Found -eq $false) {
|
||||
continue
|
||||
}
|
||||
# https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users
|
||||
if ($Registry.Key -like 'Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\*') {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
}
|
||||
$CreateGPO['Disabled'] = $Registry.Disabled
|
||||
if ($Registry.Key -like '*EscDomains*') {
|
||||
$CreateGPO['Configuration'] = 'Enhanced Security Configuration (ESC)'
|
||||
} else {
|
||||
$CreateGPO['Configuration'] = 'Domains'
|
||||
}
|
||||
if ($Registry.Hive -eq 'HKEY_CURRENT_USER') {
|
||||
$CreateGPO['Type'] = 'User Policy'
|
||||
} elseif ($Registry.Hive -eq 'HKEY_LOCAL_MACHINE') {
|
||||
$CreateGPO['Type'] = 'Computer Policy'
|
||||
} else {
|
||||
$CreateGPO['Type'] = $Registry.Hive
|
||||
}
|
||||
if ($Registry.Value -eq '00000000') {
|
||||
$CreateGPO['Zone'] = 'My Computer (0)'
|
||||
} elseif ($Registry.Value -eq '00000001') {
|
||||
$CreateGPO['Zone'] = 'Local Intranet Zone (1)'
|
||||
} elseif ($Registry.Value -eq '00000002') {
|
||||
$CreateGPO['Zone'] = 'Trusted Sites Zone (2)'
|
||||
} elseif ($Registry.Value -eq '00000003') {
|
||||
$CreateGPO['Zone'] = 'Internet Zone (3)'
|
||||
} elseif ($Registry.Value -eq '00000004') {
|
||||
$CreateGPO['Zone'] = 'Restricted Sites Zone (4)'
|
||||
} else {
|
||||
$CreateGPO['Zone'] = $Registry.Value
|
||||
}
|
||||
[string] $FullKey = foreach ($Key in $Keys) {
|
||||
if ($Registry.Key -like "$Key*") {
|
||||
$Registry.Key.Replace($Key, '')
|
||||
}
|
||||
}
|
||||
$DomainSplit = $FullKey.Split('\')
|
||||
$Reversed = for ($i = $DomainSplit.Count - 1; $i -ge 0; $i--) {
|
||||
$DomainSplit[$i]
|
||||
}
|
||||
if ($Registry.Name -eq '*') {
|
||||
$CreateGPO['DomainZone'] = $Reversed -join '.'
|
||||
} else {
|
||||
$CreateGPO['DomainZone'] = -join ($Registry.Name, '://', ($Reversed -join '.'))
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,59 +17,12 @@
|
||||
}
|
||||
|
||||
[Array] $CreateGPO['Settings'] = Get-XMLNestedRegistry -GPO $GPO -DataSet $GPO.DataSet
|
||||
<#
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Registry in $GPO.DataSet.Registry) {
|
||||
[PSCustomObject] @{
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
}
|
||||
}
|
||||
#>
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
<#
|
||||
if ($GPO.DataSet.Registry) {
|
||||
Get-XMLNestedRegistry -GPO $GPO -RegistryCollection $GPO.DataSet.Registry
|
||||
}
|
||||
if ($GPO.DataSet.Collection) {
|
||||
Get-XMLNestedRegistry -GPO $GPO -RegistryCollection $GPO.DataSet.Collection
|
||||
}
|
||||
#>
|
||||
Get-XMLNestedRegistry -GPO $GPO -DataSet $GPO.DataSet
|
||||
|
||||
<#
|
||||
foreach ($Registry in $GPO.DataSet.Registry) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
function ConvertTo-XMLUserRightsAssignment {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
|
||||
$UserRightsTranslation = @{
|
||||
SeNetworkLogonRight = 'Access this computer from the network'
|
||||
SeMachineAccountPrivilege = 'Add workstations to domain'
|
||||
SeIncreaseQuotaPrivilege = 'Adjust memory quotas for a process'
|
||||
SeInteractiveLogonRight = 'Allow log on locally'
|
||||
SeBackupPrivilege = 'Back up files and directories'
|
||||
SeChangeNotifyPrivilege = 'Bypass traverse checking Everyone'
|
||||
SeSystemTimePrivilege = 'Change the system time'
|
||||
SeCreatePagefilePrivilege = 'Create a pagefile'
|
||||
SeDebugPrivilege = 'Debug programs'
|
||||
SeEnableDelegationPrivilege = 'Enable computer and user accounts to be trusted for delegation'
|
||||
SeRemoteShutdownPrivilege = 'Force shutdown from a remote system'
|
||||
SeAuditPrivilege = 'Generate security audits'
|
||||
SeIncreaseBasePriorityPrivilege = 'Increase scheduling priority'
|
||||
SeLoadDriverPrivilege = 'Load and unload device drivers'
|
||||
SeBatchLogonRight = 'Log on as a batch job'
|
||||
SeSecurityPrivilege = 'Manage auditing and security log'
|
||||
SeSystemEnvironmentPrivilege = 'Modify firmware environment values'
|
||||
SeProfileSingleProcessPrivilege = 'Profile single process'
|
||||
SeSystemProfilePrivilege = 'Profile system performance'
|
||||
SeUndockPrivilege = 'Remove computer from docking station'
|
||||
SeAssignPrimaryTokenPrivilege = 'Replace a process level token'
|
||||
SeRestorePrivilege = 'Restore files and directories'
|
||||
SeShutdownPrivilege = 'Shut down the system'
|
||||
SeTakeOwnershipPrivilege = 'Take ownership of files or other objects'
|
||||
}
|
||||
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Entry in $GPO.DataSet) {
|
||||
foreach ($Member in $Entry.Member) {
|
||||
[PSCustomObject]@{
|
||||
'UserRightsAssignment' = $Entry.Name
|
||||
'UserRightsAssignmentDescription' = $UserRightsTranslation[$Entry.Name]
|
||||
'Name' = $Member.Name.'#text'
|
||||
'Sid' = $Member.SID.'#text'
|
||||
}
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Entry in $GPO.DataSet) {
|
||||
foreach ($Member in $Entry.Member) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
}
|
||||
$CreateGPO['UserRightsAssignment'] = $Entry.Name
|
||||
$CreateGPO['UserRightsAssignmentDescription'] = $UserRightsTranslation[$Entry.Name]
|
||||
$CreateGPO['Name'] = $Member.Name.'#text'
|
||||
$CreateGPO['Sid'] = $Member.SID.'#text'
|
||||
#$CreateGPO['CreatedTime'] = $GPO.CreatedTime # : 06.06.2020 18:03:36
|
||||
#$CreateGPO['ModifiedTime'] = $GPO.ModifiedTime # : 17.06.2020 16:08:10
|
||||
#$CreateGPO['ReadTime'] = $GPO.ReadTime # : 13.08.2020 10:15:37
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
function Find-MissingProperties {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[Array] $Objects,
|
||||
[string[]] $PossibleProperties
|
||||
)
|
||||
$AllProperties = Select-Properties -AllProperties -Objects $Objects
|
||||
$MissingProperties = $AllProperties | Where-Object { $_ -notin 'DisplayName', 'DomainName', 'GUID', 'Linked', 'LinksCount', 'Links', 'GPOType', 'GPOCategory', 'GPOSettings' }
|
||||
[Array] $ConsiderAdding = foreach ($Property in $MissingProperties) {
|
||||
if ($Property -notin $PossibleProperties) {
|
||||
$Property
|
||||
}
|
||||
}
|
||||
$ConsiderAdding
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
function Format-CamelCaseToDisplayName {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string[]] $Text,
|
||||
[string] $AddChar
|
||||
)
|
||||
foreach ($string in $Text) {
|
||||
$newString = ''
|
||||
$stringChars = $string.GetEnumerator()
|
||||
$charIndex = 0
|
||||
foreach ($char in $stringChars) {
|
||||
# If upper and not first character, add a space
|
||||
if ([char]::IsUpper($char) -eq 'True' -and $charIndex -gt 0) {
|
||||
$newString = $newString + $AddChar + $char.ToString()
|
||||
} elseif ($charIndex -eq 0) {
|
||||
# If the first character, make it a capital always
|
||||
$newString = $newString + $char.ToString().ToUpper()
|
||||
} else {
|
||||
$newString = $newString + $char.ToString()
|
||||
}
|
||||
$charIndex++
|
||||
}
|
||||
$newString
|
||||
}
|
||||
}
|
||||
|
||||
#Format-CamelCaseToDisplayName -Text 'Test1', 'TestingMyAss', 'OtherTest', 'otherTEst'
|
||||
+196
-98
@@ -5,7 +5,7 @@
|
||||
[Object] $SecurityRights,
|
||||
|
||||
[string[]] $Principal,
|
||||
[validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
[validateset('DistinguishedName', 'Name', 'NetbiosName', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
|
||||
[switch] $SkipWellKnown,
|
||||
[switch] $SkipAdministrative,
|
||||
@@ -20,7 +20,7 @@
|
||||
[switch] $IncludeGPOObject,
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups,
|
||||
[validateSet('AuthenticatedUsers', 'DomainComputers', 'Unknown', 'WellKnownAdministrative', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All')][string[]] $Type = 'All',
|
||||
[System.Collections.IDictionary] $Accounts,
|
||||
#[System.Collections.IDictionary] $Accounts,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
Begin {
|
||||
@@ -100,6 +100,11 @@
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($GPOPermission.Trustee.Domain) {
|
||||
$UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name)
|
||||
} else {
|
||||
$UserMerge = $null
|
||||
}
|
||||
if ($Principal) {
|
||||
if ($PrincipalType -eq 'Sid') {
|
||||
if ($Principal -notcontains $GPOPermission.Trustee.Sid.Value) {
|
||||
@@ -110,8 +115,11 @@
|
||||
return
|
||||
}
|
||||
} elseif ($PrincipalType -eq 'Name') {
|
||||
$UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name)
|
||||
if ($Principal -notcontains $UserMerge -and $Principal -notcontains $GPOPermission.Trustee.Name) {
|
||||
if ($Principal -notcontains $GPOPermission.Trustee.Name) {
|
||||
return
|
||||
}
|
||||
} elseif ($PrincipalType -eq 'NetbiosName') {
|
||||
if ($Principal -notcontains $UserMerge) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -126,56 +134,76 @@
|
||||
return
|
||||
}
|
||||
} elseif ($ExcludePrincipalType -eq 'Name') {
|
||||
$UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name)
|
||||
if ($ExcludePrincipal -contains $UserMerge -or $ExcludePrincipal -contains $GPOPermission.Trustee.Name) {
|
||||
if ($ExcludePrincipal -contains $GPOPermission.Trustee.Name) {
|
||||
return
|
||||
}
|
||||
} elseif ($ExcludePrincipalType -eq 'NetbiosName') {
|
||||
if ($ExcludePrincipal -contains $UserMerge) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
$ReturnObject = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName # : ALL | Enable RDP
|
||||
GUID = $GPO.ID
|
||||
DomainName = $GPO.DomainName # : ad.evotec.xyz
|
||||
Enabled = $GPO.GpoStatus
|
||||
Description = $GPO.Description
|
||||
CreationDate = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
PermissionType = if ($GPOPermission.Denied -eq $true) { 'Deny' } else { 'Allow' }
|
||||
Permission = $GPOPermission.Permission # : GpoEditDeleteModifySecurity
|
||||
Inherited = $GPOPermission.Inherited # : False
|
||||
Domain = $GPOPermission.Trustee.Domain #: EVOTEC
|
||||
DistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz
|
||||
Name = $GPOPermission.Trustee.Name #: Domain Admins
|
||||
Sid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512
|
||||
SidType = $GPOPermission.Trustee.SidType #: Group
|
||||
}
|
||||
if ($Accounts) {
|
||||
$A = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name)
|
||||
if ($A -and $Accounts[$A]) {
|
||||
$ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName
|
||||
$ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled
|
||||
$ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName
|
||||
$ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' }
|
||||
$ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' }
|
||||
if (-not $ReturnObject['Sid']) {
|
||||
$ReturnObject['Sid'] = $Accounts[$A].Sid.Value
|
||||
}
|
||||
if ($Accounts[$A].ObjectClass -eq 'group') {
|
||||
$ReturnObject['SidType'] = 'Group'
|
||||
} elseif ($Accounts[$A].ObjectClass -eq 'user') {
|
||||
$ReturnObject['SidType'] = 'User'
|
||||
} elseif ($Accounts[$A].ObjectClass -eq 'computer') {
|
||||
$ReturnObject['SidType'] = 'Computer'
|
||||
} else {
|
||||
$ReturnObject['SidType'] = 'EmptyOrUnknown'
|
||||
|
||||
<#
|
||||
# Sets permissions name, domain, distinguishedname to proper values
|
||||
if ($GPOPermission.Trustee.Name) {
|
||||
$DomainPlusName = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name)
|
||||
if ($GPOPermission.Trustee.DSPath) {
|
||||
$NetbiosConversion = ConvertFrom-NetbiosName -Identity $DomainPlusName
|
||||
if ($NetbiosConversion.DomainName) {
|
||||
$UserNameDomain = $NetbiosConversion.DomainName
|
||||
$UserName = $NetbiosConversion.Name
|
||||
}
|
||||
} else {
|
||||
$ReturnObject['UserPrincipalName'] = ''
|
||||
$ReturnObject['AccountEnabled'] = ''
|
||||
$ReturnObject['PasswordLastSet'] = ''
|
||||
$ReturnObject['LastLogonDate'] = ''
|
||||
$UserNameDomain = ''
|
||||
$Username = $DomainPlusName
|
||||
}
|
||||
} else {
|
||||
$DomainPlusName = ''
|
||||
$UserNameDomain = ''
|
||||
$Username = ''
|
||||
}
|
||||
#>
|
||||
|
||||
# I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function
|
||||
$PermissionAccount = Get-WinADObject -Identity $GPOPermission.Trustee.Sid.Value -AddType -Cache
|
||||
if ($PermissionAccount) {
|
||||
$UserNameDomain = $PermissionAccount.DomainName
|
||||
$UserName = $PermissionAccount.Name
|
||||
$SidType = $PermissionAccount.Type
|
||||
$ObjectClass = $PermissionAccount.ObjectClass
|
||||
} else {
|
||||
$ConvertFromSID = ConvertFrom-SID -SID $GPOPermission.Trustee.Sid.Value
|
||||
$UserNameDomain = ''
|
||||
$Username = $ConvertFromSID.Name
|
||||
$SidType = $ConvertFromSID.Type
|
||||
if ($SidType -eq 'Unknown') {
|
||||
$ObjectClass = 'unknown'
|
||||
} else {
|
||||
$ObjectClass = 'foreignSecurityPrincipal'
|
||||
}
|
||||
}
|
||||
$ReturnObject = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName # : ALL | Enable RDP
|
||||
GUID = $GPO.ID
|
||||
DomainName = $GPO.DomainName # : ad.evotec.xyz
|
||||
Enabled = $GPO.GpoStatus
|
||||
Description = $GPO.Description
|
||||
CreationDate = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
PermissionType = if ($GPOPermission.Denied -eq $true) { 'Deny' } else { 'Allow' }
|
||||
Permission = $GPOPermission.Permission # : GpoEditDeleteModifySecurity
|
||||
Inherited = $GPOPermission.Inherited # : False
|
||||
PrincipalNetBiosName = $UserMerge
|
||||
PrincipalDistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz
|
||||
PrincipalDomainName = $UserNameDomain #: EVOTEC
|
||||
PrincipalName = $UserName #: Domain Admins
|
||||
PrincipalSid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512
|
||||
PrincipalSidType = $SidType #$GPOPermission.Trustee.SidType #: Group
|
||||
PrincipalObjectClass = $ObjectClass
|
||||
}
|
||||
|
||||
|
||||
if ($IncludeGPOObject) {
|
||||
$ReturnObject['GPOObject'] = $GPO
|
||||
$ReturnObject['GPOSecurity'] = $SecurityRights
|
||||
@@ -183,69 +211,139 @@
|
||||
}
|
||||
[PSCustomObject] $ReturnObject
|
||||
}
|
||||
if ($IncludeOwner.IsPresent) {
|
||||
if ($IncludeOwner) {
|
||||
if ($GPO.Owner) {
|
||||
$SplittedOwner = $GPO.Owner.Split('\')
|
||||
$DomainOwner = $SplittedOwner[0] #: EVOTEC
|
||||
$DomainUserName = $SplittedOwner[1] #: Domain Admins
|
||||
$SID = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].Sid.Value
|
||||
if ($SID) {
|
||||
$SIDType = 'Group'
|
||||
$DistinguishedName = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].DistinguishedName
|
||||
# I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function
|
||||
$OwnerAccount = Get-WinADObject -Identity $GPO.Owner -AddType -Cache
|
||||
if ($OwnerAccount) {
|
||||
$UserNameDomain = $OwnerAccount.DomainName
|
||||
$UserName = $OwnerAccount.Name
|
||||
$SidType = $OwnerAccount.Type
|
||||
$OwnerObjectClass = $OwnerAccount.ObjectClass
|
||||
$SID = $OwnerAccount.ObjectSID
|
||||
} else {
|
||||
$SIDType = ''
|
||||
$DistinguishedName = ''
|
||||
$ConvertFromSID = ConvertFrom-SID -SID $GPO.Owner
|
||||
$UserNameDomain = ''
|
||||
$Username = $ConvertFromSID.Name
|
||||
$SidType = $ConvertFromSID.Type
|
||||
if ($SidType -eq 'Unknown') {
|
||||
$OwnerObjectClass = 'unknown'
|
||||
} else {
|
||||
$OwnerObjectClass = 'foreignSecurityPrincipal'
|
||||
}
|
||||
$SID = $ConvertFromSID.SID
|
||||
}
|
||||
} else {
|
||||
$DomainOwner = $GPO.Owner
|
||||
$DomainUserName = ''
|
||||
$UserName = ''
|
||||
$UserNameDomain = ''
|
||||
$SID = ''
|
||||
$SIDType = 'EmptyOrUnknown'
|
||||
$SIDType = 'Unknown'
|
||||
$DistinguishedName = ''
|
||||
$OwnerObjectClass = 'unknown'
|
||||
}
|
||||
$ReturnObject = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName # : ALL | Enable RDP
|
||||
GUID = $GPO.Id
|
||||
DomainName = $GPO.DomainName # : ad.evotec.xyz
|
||||
Enabled = $GPO.GpoStatus
|
||||
Description = $GPO.Description
|
||||
CreationDate = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity
|
||||
Inherited = $false # : False
|
||||
Domain = $DomainOwner
|
||||
DistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz
|
||||
Name = $DomainUserName
|
||||
Sid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512
|
||||
SidType = $SIDType # #: Group
|
||||
}
|
||||
if ($Accounts) {
|
||||
$A = $GPO.Owner
|
||||
if ($A -and $Accounts[$A]) {
|
||||
$ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName
|
||||
$ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled
|
||||
$ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName
|
||||
$ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' }
|
||||
$ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' }
|
||||
if (-not $ReturnObject['Sid']) {
|
||||
$ReturnObject['Sid'] = $Accounts[$A].Sid.Value
|
||||
}
|
||||
if ($Accounts[$A].ObjectClass -eq 'group') {
|
||||
$ReturnObject['SidType'] = 'Group'
|
||||
} elseif ($Accounts[$A].ObjectClass -eq 'user') {
|
||||
$ReturnObject['SidType'] = 'User'
|
||||
} elseif ($Accounts[$A].ObjectClass -eq 'computer') {
|
||||
$ReturnObject['SidType'] = 'Computer'
|
||||
} else {
|
||||
$ReturnObject['SidType'] = 'EmptyOrUnknown'
|
||||
# We have to process it for owners after querying user because $Owners are not as established as standard permissions so we don't know a lot
|
||||
|
||||
if ($Type -contains 'Administrative' -and $Type -notcontains 'All') {
|
||||
if ($SID) {
|
||||
$IsAdministrative = $ADAdministrativeGroups['BySID'][$SID]
|
||||
if (-not $IsAdministrative) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
$ReturnObject['UserPrincipalName'] = ''
|
||||
$ReturnObject['AccountEnabled'] = ''
|
||||
$ReturnObject['PasswordLastSet'] = ''
|
||||
$ReturnObject['LastLogonDate'] = ''
|
||||
# if there is no SID, it's not administrative
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'NotWellKnownAdministrative' -and $Type -notcontains 'All') {
|
||||
# We check for SYSTEM account
|
||||
# Maybe we should make it a function and provide more
|
||||
if ($SID -eq 'S-1-5-18') {
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'WellKnownAdministrative' -and $Type -notcontains 'All') {
|
||||
# We check for SYSTEM account
|
||||
# Maybe we should make it a function and provide more
|
||||
if ($SID -ne 'S-1-5-18') {
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'Unknown' -and $Type -notcontains 'All') {
|
||||
# May need updates if there's more types
|
||||
if ($SidType -ne 'Unknown') {
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'AuthenticatedUsers' -and $Type -notcontains 'All') {
|
||||
if ($SID -ne 'S-1-5-11') {
|
||||
return
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'DomainComputers' -and $Type -notcontains 'All') {
|
||||
$DomainComputersSID = -join ($ExtendedForestInformation['DomainsExtended'][$GPO.DomainName].DomainSID, '-515')
|
||||
if ($SID -ne $DomainComputersSID) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ($Principal) {
|
||||
if ($PrincipalType -eq 'Sid') {
|
||||
if ($Principal -notcontains $SID) {
|
||||
return
|
||||
}
|
||||
} elseif ($PrincipalType -eq 'DistinguishedName') {
|
||||
if ($Principal -notcontains $DistinguishedName) {
|
||||
return
|
||||
}
|
||||
} elseif ($PrincipalType -eq 'Name') {
|
||||
if ($Principal -notcontains $UserName) {
|
||||
return
|
||||
}
|
||||
} elseif ($PrincipalType -eq 'NetbiosName') {
|
||||
if ($Principal -notcontains $GPO.Owner) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($ExcludePrincipal) {
|
||||
if ($ExcludePrincipalType -eq 'Sid') {
|
||||
if ($ExcludePrincipal -contains $SID) {
|
||||
return
|
||||
}
|
||||
} elseif ($ExcludePrincipalType -eq 'DistinguishedName') {
|
||||
if ($ExcludePrincipal -contains $DistinguishedName) {
|
||||
return
|
||||
}
|
||||
} elseif ($ExcludePrincipalType -eq 'Name') {
|
||||
if ($ExcludePrincipal -contains $UserName) {
|
||||
return
|
||||
}
|
||||
} elseif ($ExcludePrincipalType -eq 'NetbiosName') {
|
||||
if ($ExcludePrincipal -contains $GPO.Owner) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ReturnObject = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName # : ALL | Enable RDP
|
||||
GUID = $GPO.Id
|
||||
DomainName = $GPO.DomainName # : ad.evotec.xyz
|
||||
Enabled = $GPO.GpoStatus
|
||||
Description = $GPO.Description
|
||||
CreationDate = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
PermissionType = 'Allow'
|
||||
Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity
|
||||
Inherited = $false # : False
|
||||
PrincipalNetBiosName = $GPO.Owner
|
||||
PrincipalDistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz
|
||||
PrincipalDomainName = $UserNameDomain
|
||||
PrincipalName = $UserName
|
||||
PrincipalSid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512
|
||||
PrincipalSidType = $SIDType # #: Group
|
||||
PrincipalObjectClass = $OwnerObjectClass
|
||||
}
|
||||
if ($IncludeGPOObject) {
|
||||
$ReturnObject['GPOObject'] = $GPO
|
||||
$ReturnObject['GPOSecurity'] = $SecurityRights
|
||||
|
||||
+37
-21
@@ -5,15 +5,33 @@
|
||||
[Microsoft.GroupPolicy.Gpo] $GPO,
|
||||
[switch] $PermissionsOnly,
|
||||
[switch] $OwnerOnly,
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups,
|
||||
[string] $Splitter = [System.Environment]::NewLine
|
||||
)
|
||||
if ($XMLContent.GPO.LinksTo) {
|
||||
$Linked = $true
|
||||
$LinksCount = ([Array] $XMLContent.GPO.LinksTo).Count
|
||||
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
|
||||
[Array] $LinksEnabled = $LinkSplit[0]
|
||||
[Array] $LinksDisabled = $LinkSplit[1]
|
||||
$LinksEnabledCount = $LinksEnabled.Count
|
||||
$LinksDisabledCount = $LinksDisabled.Count
|
||||
$LinksTotalCount = ([Array] $XMLContent.GPO.LinksTo).Count
|
||||
if ($LinksEnabledCount -eq 0) {
|
||||
$Linked = $false
|
||||
} else {
|
||||
$Linked = $true
|
||||
}
|
||||
} else {
|
||||
$Linked = $false
|
||||
$LinksCount = 0
|
||||
$LinksEnabledCount = 0
|
||||
$LinksDisabledCount = 0
|
||||
$LinksTotalCount = 0
|
||||
}
|
||||
if ($null -eq $XMLContent.GPO.Computer.ExtensionData -and $null -eq $XMLContent.GPO.User.ExtensionData) {
|
||||
$Empty = $true
|
||||
} else {
|
||||
$Empty = $false
|
||||
}
|
||||
|
||||
|
||||
# Find proper values for enabled/disabled user/computer settings
|
||||
if ($XMLContent.GPO.Computer.Enabled -eq 'False') {
|
||||
@@ -48,7 +66,7 @@
|
||||
$OwnerType = 'NotAdministrative'
|
||||
}
|
||||
} else {
|
||||
$OwnerType = 'EmptyOrUnknown'
|
||||
$OwnerType = 'Unknown'
|
||||
}
|
||||
}
|
||||
if ($PermissionsOnly) {
|
||||
@@ -98,8 +116,11 @@
|
||||
'DisplayName' = $XMLContent.GPO.Name
|
||||
'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text'
|
||||
'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}'
|
||||
'Empty' = $Empty
|
||||
'Linked' = $Linked
|
||||
'LinksCount' = $LinksCount
|
||||
'LinksCount' = $LinksTotalCount
|
||||
'LinksEnabledCount' = $LinksEnabledCount
|
||||
'LinksDisabledCount' = $LinksDisabledCount
|
||||
'Enabled' = $Enabled
|
||||
'ComputerEnabled' = $ComputerEnabled
|
||||
'UserEnabled' = $UserEnabled
|
||||
@@ -111,14 +132,11 @@
|
||||
'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
|
||||
'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false }
|
||||
'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension
|
||||
|
||||
ComputerPolicies = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
|
||||
UserPolicies = $XMLContent.GPO.User.ExtensionData.Name -join ", "
|
||||
|
||||
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
|
||||
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
|
||||
'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime
|
||||
'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime
|
||||
'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime
|
||||
|
||||
'WMIFilter' = $GPO.WmiFilter.name
|
||||
'WMIFilterDescription' = $GPO.WmiFilter.Description
|
||||
'GPODistinguishedName' = $GPO.Path
|
||||
@@ -147,7 +165,14 @@
|
||||
}
|
||||
)
|
||||
'Auditing' = if ($XMLContent.GPO.SecurityDescriptor.AuditingPresent.'#text' -eq 'true') { $true } else { $false }
|
||||
'Links' = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
'Links' = @(
|
||||
$XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
$_.SOMPath
|
||||
}
|
||||
}
|
||||
) -join $Splitter
|
||||
'LinksObjects' = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
[PSCustomObject] @{
|
||||
CanonicalName = $_.SOMPath
|
||||
@@ -156,15 +181,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
<#
|
||||
SOMName SOMPath Enabled NoOverride
|
||||
------- ------- ------- ----------
|
||||
ad ad.evotec.xyz true false
|
||||
#>
|
||||
|
||||
#| Select-Object -ExpandProperty SOMPath
|
||||
|
||||
}
|
||||
}
|
||||
#break
|
||||
}
|
||||
@@ -9,57 +9,24 @@ function Get-XMLNestedRegistry {
|
||||
if ($DataSet.Properties) {
|
||||
$Registry = $DataSet
|
||||
foreach ($Registry in $DataSet) {
|
||||
if ($Limited) {
|
||||
[PSCustomObject] @{
|
||||
Collection = $Collection
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
}
|
||||
} else {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Collection = $Collection
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($Name in @('Registry', 'Collection')) {
|
||||
foreach ($Registry in $DataSet.$Name) {
|
||||
if ($Registry.Properties) {
|
||||
if ($Limited) {
|
||||
[PSCustomObject] @{
|
||||
Collection = $Collection
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Description = $Registry.descr
|
||||
Changed = try { [DateTime] $Registry.changed } catch { $Registry.changed };
|
||||
Disabled = if ($Registry.disabled -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = [int] $Registry.GPOSettingOrder
|
||||
Action = $Script:Actions[$Registry.Properties.action]
|
||||
DisplayDecimal = if ($Registry.Properties.displayDecimal -eq '1') { $true } else { $false };
|
||||
Default = if ($Registry.Properties.default -eq '1') { $true } else { $false };
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
BypassErrors = if ($Registry.bypassErrors -eq '1') { $true } else { $false };
|
||||
}
|
||||
} else {
|
||||
$CreateGPO = [ordered]@{
|
||||
@@ -70,14 +37,73 @@ function Get-XMLNestedRegistry {
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Collection = $Collection
|
||||
Changed = [DateTime] $Registry.changed
|
||||
GPOSettingOrder = $Registry.GPOSettingOrder
|
||||
Description = $Registry.descr
|
||||
Changed = try { [DateTime] $Registry.changed } catch { $Registry.changed };
|
||||
Disabled = if ($Registry.disabled -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = [int] $Registry.GPOSettingOrder
|
||||
Action = $Script:Actions[$Registry.Properties.action]
|
||||
DisplayDecimal = if ($Registry.Properties.displayDecimal -eq '1') { $true } else { $false };
|
||||
Default = if ($Registry.Properties.default -eq '1') { $true } else { $false };
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
BypassErrors = if ($Registry.bypassErrors -eq '1') { $true } else { $false };
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($Name in @('Registry', 'Collection')) {
|
||||
foreach ($Registry in $DataSet.$Name) {
|
||||
if ($Registry.Properties) {
|
||||
if ($Limited) {
|
||||
[PSCustomObject] @{
|
||||
Collection = $Collection
|
||||
Description = $Registry.descr
|
||||
Changed = try { [DateTime] $Registry.changed } catch { $Registry.changed };
|
||||
Disabled = if ($Registry.disabled -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = [int] $Registry.GPOSettingOrder
|
||||
Action = $Script:Actions[$Registry.Properties.action]
|
||||
DisplayDecimal = if ($Registry.Properties.displayDecimal -eq '1') { $true } else { $false };
|
||||
Default = if ($Registry.Properties.default -eq '1') { $true } else { $false };
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
BypassErrors = if ($Registry.bypassErrors -eq '1') { $true } else { $false };
|
||||
}
|
||||
} else {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Collection = $Collection
|
||||
Description = $Registry.descr
|
||||
Changed = try { [DateTime] $Registry.changed } catch { $Registry.changed };
|
||||
Disabled = if ($Registry.disabled -eq '1') { $true } else { $false };
|
||||
GPOSettingOrder = [int] $Registry.GPOSettingOrder
|
||||
Action = $Script:Actions[$Registry.Properties.action]
|
||||
DisplayDecimal = if ($Registry.Properties.displayDecimal -eq '1') { $true } else { $false }; ;
|
||||
Default = if ($Registry.Properties.default -eq '1') { $true } else { $false };
|
||||
Hive = $Registry.Properties.hive #: HKEY_LOCAL_MACHINE
|
||||
Key = $Registry.Properties.key #: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
|
||||
Name = $Registry.Properties.name #: AutoAdminLogon
|
||||
Type = $Registry.Properties.type #: REG_SZ
|
||||
Value = $Registry.Properties.value #
|
||||
Filters = $Registry.Filters
|
||||
BypassErrors = if ($Registry.bypassErrors -eq '1') { $true } else { $false };
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
@@ -86,10 +112,12 @@ function Get-XMLNestedRegistry {
|
||||
}
|
||||
} else {
|
||||
if ($Registry.Registry) {
|
||||
#$Collection = $Registry.name
|
||||
#if ($Registry.Name.Count -gt 1) {
|
||||
#Write-Verbose "Registry Name count more than 1"
|
||||
#}
|
||||
$TempCollection = $Collection
|
||||
if ($Collection) {
|
||||
$Collection = "$Collection\$($Registry.name)"
|
||||
$Collection = "$Collection/$($Registry.name)"
|
||||
} else {
|
||||
$Collection = $Registry.name
|
||||
}
|
||||
@@ -97,12 +125,24 @@ function Get-XMLNestedRegistry {
|
||||
$Collection = $TempCollection
|
||||
}
|
||||
if ($Registry.Collection) {
|
||||
if ($Collection) {
|
||||
$Collection = "$Collection\$($Registry.Collection.name)"
|
||||
} else {
|
||||
$Collection = "$($Registry.name)\$($Registry.Collection.name)"
|
||||
$TempCollection = $Collection
|
||||
#if ($Registry.Collection.Count -gt 1) {
|
||||
# Write-Verbose "Registry collection count more than 1"
|
||||
#}
|
||||
foreach ($MyCollection in $Registry.Collection) {
|
||||
if ($Collection) {
|
||||
#Write-Verbose "Collection1: $Collection - $($Registry.name) - $($MyCollection.name) - $($($MyCollection.name).Count)"
|
||||
$Collection = "$Collection/$($Registry.name)/$($MyCollection.name)"
|
||||
#Write-Verbose "Collection2: $Collection"
|
||||
} else {
|
||||
#Write-Verbose "Collection3: $Collection - $($Registry.name) - $($MyCollection.name)"
|
||||
$Collection = "$($Registry.name)/$($MyCollection.name)"
|
||||
#Write-Verbose "Collection4: $Collection"
|
||||
}
|
||||
|
||||
Get-XMLNestedRegistry -GPO $GPO -DataSet $MyCollection -Collection $Collection
|
||||
$Collection = $TempCollection
|
||||
}
|
||||
Get-XMLNestedRegistry -GPO $GPO -DataSet $Registry.Collection -Collection $Collection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
function Get-XMLOutput {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[System.Xml.XmlElement[]] $GPOOutput,
|
||||
[string] $Splitter,
|
||||
[switch] $FullObjects
|
||||
)
|
||||
$LinksInformation = Get-LinksFromXML -GPOOutput $GPOOutput -Splitter $Splitter -FullObjects:$FullObjects
|
||||
foreach ($GpoType in @('User', 'Computer')) {
|
||||
if ($GPOOutput.$GpoType.ExtensionData.Extension) {
|
||||
foreach ($ExtensionType in $GPOOutput.$GpoType.ExtensionData.Extension) {
|
||||
# It's possible that one of the ExtensionType records has value null. Weird but happend.
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLStandard - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
foreach ($GpoSettings in $KeysToLoop.Name) {
|
||||
$Template = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.Guid
|
||||
GpoType = $GpoType
|
||||
GpoCategory = $GPOSettingTypeSplit[1]
|
||||
GpoSettings = $GpoSettings
|
||||
}
|
||||
[PSCustomObject] $Template
|
||||
}
|
||||
continue
|
||||
|
||||
foreach ($GpoSettings in $KeysToLoop.Name) {
|
||||
foreach ($Key in $ExtensionType.$GpoSettings) {
|
||||
$Template = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.Guid
|
||||
GpoType = $GpoType
|
||||
GpoCategory = $GPOSettingTypeSplit[1]
|
||||
GpoSettings = $GpoSettings
|
||||
}
|
||||
try {
|
||||
$Properties = ($Key | Get-Member -MemberType Properties -ErrorAction Stop).Name
|
||||
} catch {
|
||||
Write-Warning "Get-XMLStandard - things went sideways 1 $($_.Exception.Message)"
|
||||
$Properties = $null
|
||||
}
|
||||
foreach ($Property in $Properties) {
|
||||
$Template["$Property"] = $Key.$Property
|
||||
}
|
||||
$Template['Linked'] = $LinksInformation.Linked
|
||||
$Template['LinksCount'] = $LinksInformation.LinksCount
|
||||
$Template['Links'] = $LinksInformation.Links
|
||||
<#
|
||||
$Template['IncludeComments'] = $GPOOutput.IncludeComments # : true #: true
|
||||
$Template['CreatedTime'] = $GPOOutput.CreatedTime # : 2020-06-17T11:23:22 #: 2020-06-17T11:23:22
|
||||
$Template['ModifiedTime'] = $GPOOutput.ModifiedTime # : 2020-06-28T15:49:52 #: 2020-06-28T15:49:52
|
||||
$Template['ReadTime'] = $GPOOutput.ReadTime # : 2020-06-28T16:14:09.2209011Z #: 2020-06-28T16:14:09.2209011Z
|
||||
$Template['SecurityDescriptor'] = $GPOOutput.SecurityDescriptor # : SecurityDescriptor #: SecurityDescriptor
|
||||
$Template['FilterDataAvailable'] = $GPOOutput.FilterDataAvailable # : true #: true
|
||||
#>
|
||||
[PSCustomObject] $Template
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
function Get-XMLStandard {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[System.Xml.XmlElement[]] $GPOOutput,
|
||||
[string] $Splitter,
|
||||
[switch] $FullObjects
|
||||
)
|
||||
$LinksInformation = Get-LinksFromXML -GPOOutput $GPOOutput -Splitter $Splitter -FullObjects:$FullObjects
|
||||
foreach ($GpoType in @('User', 'Computer')) {
|
||||
if ($GPOOutput.$GpoType.ExtensionData.Extension) {
|
||||
foreach ($ExtensionType in $GPOOutput.$GpoType.ExtensionData.Extension) {
|
||||
# It's possible that one of the ExtensionType records has value null. Weird but happend.
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLStandard - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
foreach ($GpoSettings in $KeysToLoop.Name) {
|
||||
foreach ($Key in $ExtensionType.$GpoSettings) {
|
||||
$Template = [ordered] @{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.Guid
|
||||
GpoType = $GpoType
|
||||
GpoCategory = $GPOSettingTypeSplit[1]
|
||||
GpoSettings = $GpoSettings
|
||||
}
|
||||
try {
|
||||
$Properties = ($Key | Get-Member -MemberType Properties -ErrorAction Stop).Name
|
||||
} catch {
|
||||
Write-Warning "Get-XMLStandard - things went sideways 1 $($_.Exception.Message)"
|
||||
$Properties = $null
|
||||
}
|
||||
foreach ($Property in $Properties) {
|
||||
$Template["$Property"] = $Key.$Property
|
||||
}
|
||||
$Template['Linked'] = $LinksInformation.Linked
|
||||
$Template['LinksCount'] = $LinksInformation.LinksCount
|
||||
$Template['Links'] = $LinksInformation.Links
|
||||
<#
|
||||
$Template['IncludeComments'] = $GPOOutput.IncludeComments # : true #: true
|
||||
$Template['CreatedTime'] = $GPOOutput.CreatedTime # : 2020-06-17T11:23:22 #: 2020-06-17T11:23:22
|
||||
$Template['ModifiedTime'] = $GPOOutput.ModifiedTime # : 2020-06-28T15:49:52 #: 2020-06-28T15:49:52
|
||||
$Template['ReadTime'] = $GPOOutput.ReadTime # : 2020-06-28T16:14:09.2209011Z #: 2020-06-28T16:14:09.2209011Z
|
||||
$Template['SecurityDescriptor'] = $GPOOutput.SecurityDescriptor # : SecurityDescriptor #: SecurityDescriptor
|
||||
$Template['FilterDataAvailable'] = $GPOOutput.FilterDataAvailable # : true #: true
|
||||
#>
|
||||
[PSCustomObject] $Template
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
function Invoke-GPOTranslation {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Collections.IDictionary] $InputData,
|
||||
[string] $Report,
|
||||
[string] $Category,
|
||||
[string] $Settings
|
||||
)
|
||||
if ($Category -and $Settings -and $InputData) {
|
||||
if ($Script:GPODitionary[$Report]['Code']) {
|
||||
$Script:GPOList = $InputData.$Category.$Settings
|
||||
return & $Script:GPODitionary[$Report]['Code']
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
function New-ADForestDrives {
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
[string] $ForestName,
|
||||
[string] $ObjectDN
|
||||
)
|
||||
if (-not $Global:ADDrivesMapped) {
|
||||
if ($ForestName) {
|
||||
$Forest = Get-ADForest -Identity $ForestName
|
||||
} else {
|
||||
$Forest = Get-ADForest
|
||||
}
|
||||
if ($ObjectDN) {
|
||||
# This doesn't work because no Domain and no $Server
|
||||
$DNConverted = (ConvertFrom-Distinguishedname -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ','
|
||||
if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) {
|
||||
try {
|
||||
|
||||
if ($Server) {
|
||||
$null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false
|
||||
Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $($Server.Hostname[0])"
|
||||
} else {
|
||||
$null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $($Server.Hostname[0])"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($Domain in $Forest.Domains) {
|
||||
try {
|
||||
$Server = Get-ADDomainController -Discover -DomainName $Domain
|
||||
$DomainInformation = Get-ADDomain -Server $Server.Hostname[0]
|
||||
} catch {
|
||||
Write-Warning "New-ADForestDrives - Can't process domain $Domain - $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
$ObjectDN = $DomainInformation.DistinguishedName
|
||||
$DNConverted = (ConvertFrom-Distinguishedname -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ','
|
||||
if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) {
|
||||
try {
|
||||
if ($Server) {
|
||||
$null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false
|
||||
Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $Server"
|
||||
} else {
|
||||
$null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $Server $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$Global:ADDrivesMapped = $true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
function New-GPOZaurrReportConsole {
|
||||
param(
|
||||
[System.Collections.IDictionary] $Results
|
||||
)
|
||||
Begin {
|
||||
$GPODeny = @{
|
||||
Color = 'Yellow', 'Red', 'Yellow', 'Red'
|
||||
StartSpaces = 6
|
||||
}
|
||||
$GPOSuccess = @{
|
||||
Color = 'Yellow', 'Green', 'Yellow', 'Green'
|
||||
StartSpaces = 6
|
||||
}
|
||||
$WriteSummary = @{
|
||||
Color = 'Yellow', 'Blue'
|
||||
StartSpaces = 3
|
||||
}
|
||||
$ComputerWhereApplied = ($Results.ComputerResults.GroupPolicies | Sort-Object -Property DomainName, Name).Where( { $_.Status -eq 'Applied' }, 'split')
|
||||
$UserWhereApplied = ($Results.UserResults.GroupPolicies | Sort-Object -Property Name).Where( { $_.Status -eq 'Applied' }, 'split')
|
||||
}
|
||||
Process {
|
||||
Write-Color -Text 'Computer Settings' -Color White -LinesBefore 1
|
||||
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.ComputerResults.Summary.ReadTime @WriteSummary
|
||||
Write-Color -Text '[>] Computer Name: ', $Results.ComputerResults.Summary.ComputerName @WriteSummary
|
||||
Write-Color -Text '[>] Domain Name: ', $Results.ComputerResults.Summary.DomainName @WriteSummary
|
||||
Write-Color -Text '[>] Organizational Unit: ', $Results.ComputerResults.Summary.OrganizationalUnit @WriteSummary
|
||||
Write-Color -Text '[>] Site: ', $Results.ComputerResults.Summary.Site @WriteSummary
|
||||
Write-Color -Text '[>] GPO Types: ', ($Results.ComputerResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
|
||||
Write-Color -Text '[>] Slow link: ', ($Results.ComputerResults.Summary.SlowLink) @WriteSummary
|
||||
|
||||
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3 -LinesBefore 1
|
||||
foreach ($GPO in $ComputerWhereApplied[0]) {
|
||||
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
|
||||
}
|
||||
|
||||
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $ComputerWhereApplied[1]) {
|
||||
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
|
||||
}
|
||||
|
||||
Write-Color -Text 'User Settings' -Color Yellow -LinesBefore 1
|
||||
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $UserWhereApplied[0] ) {
|
||||
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
|
||||
}
|
||||
|
||||
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $UserWhereApplied[1]) {
|
||||
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
function New-GPOZaurrReportHTML {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Collections.IDictionary] $Support,
|
||||
[string] $Path,
|
||||
[switch] $Offline,
|
||||
[switch] $Open
|
||||
)
|
||||
$PSDefaultParameterValues = @{
|
||||
"New-HTMLTable:WarningAction" = 'SilentlyContinue'
|
||||
}
|
||||
if (-not $Path) {
|
||||
$Path = [io.path]::GetTempFileName().Replace('.tmp', ".html")
|
||||
}
|
||||
$ComputerName = $($Support.ResultantSetPolicy.LoggingComputer)
|
||||
#$UserName = $($Support.ResultantSetPolicy.UserName)
|
||||
#$LoggingMode = $($Support.ResultantSetPolicy.LoggingMode)
|
||||
New-HTML -TitleText "Group Policy Report - $ComputerName" {
|
||||
#New-HTMLTabOptions -SlimTabs -Transition -LinearGradient -SelectorColor Akaroa
|
||||
New-HTMLTabOptions -SlimTabs `
|
||||
-BorderBottomStyleActive solid -BorderBottomColorActive LightSkyBlue -BackgroundColorActive none `
|
||||
-TextColorActive Black -Align left -BorderRadius 0px -RemoveShadow -TextColor Grey -TextTransform capitalize
|
||||
New-HTMLTab -Name 'Information' {
|
||||
New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter
|
||||
}
|
||||
foreach ($Key in $Support.Keys) {
|
||||
if ($Key -eq 'ResultantSetPolicy') {
|
||||
continue
|
||||
}
|
||||
New-HTMLTab -Name $Key {
|
||||
New-HTMLTab -Name 'Summary' {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLSection -HeaderText 'Summary' {
|
||||
New-HTMLTable -DataTable $Support.$Key.Summary -Filtering -PagingOptions @(7, 14 )
|
||||
New-HTMLTable -DataTable $Support.$Key.SummaryDetails -Filtering -PagingOptions @(7, 14)
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Part of Security Groups' {
|
||||
New-HTMLTable -DataTable $Support.$Key.SecurityGroups -Filtering -PagingOptions @(7, 14)
|
||||
}
|
||||
}
|
||||
<#
|
||||
New-HTMLSection -HeaderText 'Summary Downloads' {
|
||||
New-HTMLTable -DataTable $Support.$Key.SummaryDownload -HideFooter
|
||||
}
|
||||
#>
|
||||
New-HTMLSection -HeaderText 'Resultant Set Policy' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ResultantSetPolicy -HideFooter
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'Group Policies' {
|
||||
New-HTMLSection -Invisible {
|
||||
<#
|
||||
New-HTMLSection -HeaderText 'Processing Time' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ProcessingTime -Filtering
|
||||
}
|
||||
#>
|
||||
New-HTMLSection -HeaderText 'ExtensionStatus' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ExtensionStatus -Filtering
|
||||
}
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPolicies -Filtering
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies Links' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPoliciesLinks -Filtering
|
||||
}
|
||||
<#
|
||||
New-HTMLSection -HeaderText 'Group Policies Applied' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPoliciesApplied -Filtering
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies Denied' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPoliciesDenied -Filtering
|
||||
}
|
||||
#>
|
||||
}
|
||||
New-HTMLTab -Name 'Extension Data' {
|
||||
New-HTMLSection -HeaderText 'Extension Data' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ExtensionData -Filtering
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'Scope of Management' {
|
||||
New-HTMLSection -HeaderText 'Scope of Management' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ScopeOfManagement -Filtering
|
||||
}
|
||||
}
|
||||
<#
|
||||
New-HTMLTab -Name 'Events By ID' {
|
||||
foreach ($ID in $Support.$Key.EventsByID.Keys) {
|
||||
New-HTMLSection -HeaderText "Event ID $ID" {
|
||||
New-HTMLTable -DataTable $Support.$Key.EventsByID[$ID] -Filtering -AllProperties
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'Events' {
|
||||
New-HTMLSection -HeaderText 'Events' {
|
||||
New-HTMLTable -DataTable $Support.$Key.Events -Filtering -AllProperties
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
||||
if ($Support.ComputerResults.Results) {
|
||||
New-HTMLTab -Name 'Details' {
|
||||
foreach ($Detail in $Support.ComputerResults.Results.Keys) {
|
||||
$ShortDetails = $Support.ComputerResults.Results[$Detail]
|
||||
New-HTMLTab -Name $Detail {
|
||||
New-HTMLTab -Name 'Test' {
|
||||
New-HTMLSection -HeaderText 'Summary Downloads' {
|
||||
New-HTMLTable -DataTable $ShortDetails.SummaryDownload -HideFooter
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Processing Time' {
|
||||
New-HTMLTable -DataTable $ShortDetails.ProcessingTime -Filtering
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies Applied' {
|
||||
New-HTMLTable -DataTable $ShortDetails.GroupPoliciesApplied -Filtering
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies Denied' {
|
||||
New-HTMLTable -DataTable $ShortDetails.GroupPoliciesDenied -Filtering
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'Events By ID' {
|
||||
foreach ($ID in $ShortDetails.EventsByID.Keys) {
|
||||
New-HTMLSection -HeaderText "Event ID $ID" {
|
||||
New-HTMLTable -DataTable $ShortDetails.EventsByID[$ID] -Filtering -AllProperties
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'Events' {
|
||||
New-HTMLSection -HeaderText 'Events' {
|
||||
New-HTMLTable -DataTable $ShortDetails.Events -Filtering -AllProperties
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online:(-not $Offline.IsPresent) -Open:$Open.IsPresent -FilePath $Path
|
||||
}
|
||||
+1061
-28
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
$Script:GPOPropetiesComputers = [ordered] @{
|
||||
'Account' = ''
|
||||
'Audit' = ''
|
||||
'AuditSetting' = ''
|
||||
'AutoEnrollmentSettings' = ''
|
||||
'Blocked' = ''
|
||||
'certSettingsTrustedPublishers' = ''
|
||||
'DataSourcesSettings' = ''
|
||||
'DomainProfile' = ''
|
||||
'Dot3SvcSetting' = ''
|
||||
'EFSRecoveryAgent' = ''
|
||||
'EFSSettings' = ''
|
||||
'EnvironmentVariables' = ''
|
||||
'EventLog' = ''
|
||||
'File' = ''
|
||||
'FilesSettings' = ''
|
||||
'Folders' = ''
|
||||
'General' = ''
|
||||
'Global' = ''
|
||||
'GlobalSettings' = ''
|
||||
'InboundFirewallRules' = ''
|
||||
'IntermediateCACertificate' = ''
|
||||
'InternetZoneRule' = ''
|
||||
'LocalUsersAndGroups' = ''
|
||||
'MsiApplication' = ''
|
||||
'NetworkOptions' = ''
|
||||
'NetworkShares' = ''
|
||||
'NTServices' = ''
|
||||
'OutboundFirewallRules' = ''
|
||||
'PathRule' = ''
|
||||
'Policy' = ''
|
||||
'PowerOptions' = ''
|
||||
'PrinterConnection' = ''
|
||||
'Printers' = ''
|
||||
'PrivateProfile' = ''
|
||||
'PublicProfile' = ''
|
||||
'Registry' = ''
|
||||
'RegistrySetting' = ''
|
||||
'RegistrySettings' = ''
|
||||
'RestrictedGroups' = ''
|
||||
'RootCertificate' = ''
|
||||
'RootCertificateSettings' = ''
|
||||
'ScheduledTasks' = ''
|
||||
'Script' = ''
|
||||
'SecurityOptions' = ''
|
||||
'ShortcutSettings' = ''
|
||||
'SystemServices' = ''
|
||||
'TrustedPublishersCertificate' = ''
|
||||
'type' = ''
|
||||
'UserRightsAssignment' = ''
|
||||
'WLanSvcSetting' = ''
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
$Script:GPOPropertiesUsers = [ordered] @{
|
||||
'AutoDetectConfigSettings' = ''
|
||||
'AutoEnrollmentSettings' = ''
|
||||
'AutomaticConfiguration' = ''
|
||||
'AutoSetupSetting' = ''
|
||||
'Blocked' = ''
|
||||
'BrowserTitle' = ''
|
||||
'CustomSetupSetting' = ''
|
||||
'DataSourcesSettings' = ''
|
||||
'DefinesConnectionSettings' = ''
|
||||
'DefinesEscOffSettings' = ''
|
||||
'DefinesEscOnSettings' = ''
|
||||
'DeleteChannels' = ''
|
||||
'DriveMapSettings' = ''
|
||||
'EscOffLocalSites' = ''
|
||||
'EscOffSecurityZoneAndPrivacy' = ''
|
||||
'EscOffTrustedSites' = ''
|
||||
'EscOnLocalSites' = ''
|
||||
'EscOnSecurityZoneAndPrivacy' = ''
|
||||
'EscOnTrustedSites' = ''
|
||||
'FavoriteURL' = ''
|
||||
'FilesSettings' = ''
|
||||
'Folder' = ''
|
||||
'FolderOptions' = ''
|
||||
'Folders' = ''
|
||||
'General' = ''
|
||||
'HomePage' = ''
|
||||
'ImportedContentRatings' = ''
|
||||
'InternetOptions' = ''
|
||||
'LocalUsersAndGroups' = ''
|
||||
'MsiApplication' = ''
|
||||
'NetworkOptions' = ''
|
||||
'PathRule' = ''
|
||||
'PlaceFavoritesAtTop' = ''
|
||||
'Policy' = ''
|
||||
'PowerOptions' = ''
|
||||
'PreferenceMode' = ''
|
||||
'PrinterConnection' = ''
|
||||
'Printers' = ''
|
||||
'Programs' = ''
|
||||
'ProxySettings' = ''
|
||||
'RegionalOptionsSettings' = ''
|
||||
'RegistrySetting' = ''
|
||||
'RegistrySettings' = ''
|
||||
'RestartSetupSetting' = ''
|
||||
'ScheduledTasks' = ''
|
||||
'Script' = ''
|
||||
'SearchBar' = ''
|
||||
'ShortcutSettings' = ''
|
||||
'StartMenuSettings' = ''
|
||||
'ToolsSetting' = ''
|
||||
'TrustedPublisherLockdown' = ''
|
||||
'type' = ''
|
||||
}
|
||||
@@ -3,14 +3,17 @@
|
||||
param(
|
||||
[Array] $GPOs,
|
||||
[string] $Server,
|
||||
[string] $Domain
|
||||
[string] $Domain,
|
||||
[System.Collections.IDictionary] $PoliciesAD,
|
||||
[string] $PoliciesSearchBase
|
||||
)
|
||||
$Differences = @{ }
|
||||
$SysvolHash = @{ }
|
||||
|
||||
$GPOGUIDS = $GPOs.ID.GUID
|
||||
$SysVolPath = "\\$($Server)\SYSVOL\$Domain\Policies"
|
||||
try {
|
||||
$SYSVOL = Get-ChildItem -Path "\\$($Server)\SYSVOL\$Domain\Policies" -ErrorAction Stop
|
||||
$SYSVOL = Get-ChildItem -Path "\\$($Server)\SYSVOL\$Domain\Policies" -Exclude 'PolicyDefinitions' -ErrorAction Stop -Verbose:$false
|
||||
} catch {
|
||||
$Sysvol = $Null
|
||||
}
|
||||
@@ -22,12 +25,20 @@
|
||||
if ($Files) {
|
||||
$Comparing = Compare-Object -ReferenceObject $GPOGUIDS -DifferenceObject $Files -IncludeEqual
|
||||
foreach ($_ in $Comparing) {
|
||||
if ($_.InputObject -eq 'PolicyDefinitions') {
|
||||
# we skip policy definitions
|
||||
continue
|
||||
}
|
||||
if ($_.SideIndicator -eq '==') {
|
||||
$Found = 'Exists'
|
||||
} elseif ($_.SideIndicator -eq '<=') {
|
||||
$Found = 'Not available on SYSVOL'
|
||||
} elseif ($_.SideIndicator -eq '=>') {
|
||||
$Found = 'Orphaned GPO'
|
||||
if ($PoliciesAD[$_.InputObject]) {
|
||||
$Found = $PoliciesAD[$_.InputObject]
|
||||
} else {
|
||||
$Found = 'Not available in AD'
|
||||
}
|
||||
} else {
|
||||
$Found = 'Orphaned GPO'
|
||||
}
|
||||
@@ -39,78 +50,81 @@
|
||||
if ($null -ne $SysvolHash[$GPO.Id.GUID].FullName) {
|
||||
$FullPath = $SysvolHash[$GPO.Id.GUID].FullName
|
||||
try {
|
||||
$ACL = Get-Acl -Path $SysvolHash[$GPO.Id.GUID].FullName -ErrorAction Stop
|
||||
$ACL = Get-Acl -Path $SysvolHash[$GPO.Id.GUID].FullName -ErrorAction Stop -Verbose:$false
|
||||
$Owner = $ACL.Owner
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrSysvol - ACL reading (1) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
Write-Warning "Get-GPOZaurrBroken - ACL reading (1) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
$ACL = $null
|
||||
$Owner = ''
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
}
|
||||
} else {
|
||||
$FullPath = -join ($SysVolPath, "\{$($GPO.Id.Guid)}")
|
||||
$ACL = $null
|
||||
$Owner = ''
|
||||
$ErrorMessage = 'Not found on SYSVOL'
|
||||
}
|
||||
if ($null -eq $Differences[$GPO.Id.Guid]) {
|
||||
$SysVolStatus = 'Not available on SYSVOL'
|
||||
$SysVolStatus = 'Unknown Issue'
|
||||
} else {
|
||||
$SysVolStatus = $Differences[$GPO.Id.Guid]
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $GPO.DisplayName
|
||||
Status = $Differences[$GPO.Id.Guid]
|
||||
DomainName = $GPO.DomainName
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = $SysVolStatus
|
||||
Owner = $GPO.Owner
|
||||
FileOwner = $Owner
|
||||
Id = $GPO.Id.Guid
|
||||
GpoStatus = $GPO.GpoStatus
|
||||
Path = $FullPath
|
||||
Description = $GPO.Description
|
||||
CreationTime = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
UserVersion = $GPO.UserVersion
|
||||
ComputerVersion = $GPO.ComputerVersion
|
||||
WmiFilter = $GPO.WmiFilter
|
||||
Error = $ErrorMessage
|
||||
DisplayName = $GPO.DisplayName
|
||||
Status = $SysVolStatus
|
||||
DomainName = $GPO.DomainName
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = $SysVolStatus
|
||||
GpoStatus = $GPO.GpoStatus
|
||||
Owner = $GPO.Owner
|
||||
FileOwner = $Owner
|
||||
Id = $GPO.Id.Guid
|
||||
Path = $FullPath
|
||||
DistinguishedName = -join ("CN={", $GPO.Id.Guid, "},", $PoliciesSearchBase)
|
||||
Description = $GPO.Description
|
||||
CreationTime = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
UserVersion = $GPO.UserVersion
|
||||
ComputerVersion = $GPO.ComputerVersion
|
||||
WmiFilter = $GPO.WmiFilter
|
||||
Error = $ErrorMessage
|
||||
}
|
||||
}
|
||||
# Now we need to list thru Sysvol files and fine those that do not exists as GPO and create dummy GPO objects to show orphaned gpos
|
||||
foreach ($_ in $Differences.Keys) {
|
||||
if ($Differences[$_] -eq 'Orphaned GPO') {
|
||||
if ($SysvolHash[$_].BaseName -notcontains 'PolicyDefinitions') {
|
||||
$FullPath = $SysvolHash[$_].FullName
|
||||
try {
|
||||
$ACL = Get-Acl -Path $FullPath -ErrorAction Stop
|
||||
$Owner = $ACL.Owner
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrSysvol - ACL reading (2) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
$ACL = $null
|
||||
$Owner = $null
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
}
|
||||
if ($Differences[$_] -in 'Not available in AD', 'Permissions issue') {
|
||||
$FullPath = $SysvolHash[$_].FullName
|
||||
try {
|
||||
$ACL = Get-Acl -Path $FullPath -ErrorAction Stop
|
||||
$Owner = $ACL.Owner
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBroken - ACL reading (2) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
$ACL = $null
|
||||
$Owner = $null
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
}
|
||||
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $SysvolHash[$_].BaseName
|
||||
Status = 'Orphaned GPO'
|
||||
DomainName = $Domain
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = $Differences[$GPO.Id.Guid]
|
||||
Owner = ''
|
||||
FileOwner = $Owner
|
||||
Id = $_
|
||||
GpoStatus = 'Orphaned'
|
||||
Path = $FullPath
|
||||
Description = $null
|
||||
CreationTime = $SysvolHash[$_].CreationTime
|
||||
ModificationTime = $SysvolHash[$_].LastWriteTime
|
||||
UserVersion = $null
|
||||
ComputerVersion = $null
|
||||
WmiFilter = $null
|
||||
Error = $ErrorMessage
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $SysvolHash[$_].BaseName
|
||||
Status = $Differences[$_]
|
||||
DomainName = $Domain
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = 'Exists' #$Differences[$GPO.Id.Guid]
|
||||
GpoStatus = $Differences[$_]
|
||||
Owner = ''
|
||||
FileOwner = $Owner
|
||||
Id = $_
|
||||
Path = $FullPath
|
||||
DistinguishedName = -join ("CN={", $_, "},", $PoliciesSearchBase)
|
||||
Description = $null
|
||||
CreationTime = $SysvolHash[$_].CreationTime
|
||||
ModificationTime = $SysvolHash[$_].LastWriteTime
|
||||
UserVersion = $null
|
||||
ComputerVersion = $null
|
||||
WmiFilter = $null
|
||||
Error = $ErrorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
function Clear-GPOZaurrSysvolDFSR {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[string[]] $ExcludeDomainControllers,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
|
||||
[switch] $SkipRODC,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[int] $LimitProcessing = [int32]::MaxValue
|
||||
)
|
||||
# Based on https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/manually-clearing-the-conflictanddeleted-folder-in-dfsr/ba-p/395711
|
||||
$StatusCodes = @{
|
||||
'0' = 'Success' # MONITOR_STATUS_SUCCESS
|
||||
'1' = 'Generic database error' #MONITOR_STATUS_GENERIC_DB_ERROR
|
||||
'2' = 'ID record not found' # MONITOR_STATUS_IDRECORD_NOT_FOUND
|
||||
'3' = 'Volume not found' # MONITOR_STATUS_VOLUME_NOT_FOUND
|
||||
'4' = 'Access denied' #MONITOR_STATUS_ACCESS_DENIED
|
||||
'5' = 'Generic error' #MONITOR_STATUS_GENERIC_ERROR
|
||||
}
|
||||
|
||||
#WMIC.EXE /namespace:\\root\microsoftdfs path dfsrreplicatedfolderconfig get replicatedfolderguid, replicatedfoldername
|
||||
#WMIC.EXE /namespace:\\root\microsoftdfs path dfsrreplicatedfolderinfo where "replicatedfolderguid='<RF GUID>'" call cleanupconflictdirectory
|
||||
#WMIC.EXE /namespace:\\root\microsoftdfs path dfsrreplicatedfolderinfo where "replicatedfolderguid='70bebd41-d5ae-4524-b7df-4eadb89e511e'" call cleanupconflictdirectory
|
||||
|
||||
# https://docs.microsoft.com/en-us/previous-versions/windows/desktop/dfsr/dfsrreplicatedfolderinfo
|
||||
$getGPOZaurrSysvolDFSRSplat = @{
|
||||
Forest = $Forest
|
||||
IncludeDomains = $IncludeDomains
|
||||
ExcludeDomains = $ExcludeDomains
|
||||
ExtendedForestInformation = $ExtendedForestInformation
|
||||
ExcludeDomainControllers = $ExcludeDomainControllers
|
||||
IncludeDomainControllers = $IncludeDomainControllers
|
||||
SkipRODC = $SkipRODC
|
||||
}
|
||||
Get-GPOZaurrSysvolDFSR @getGPOZaurrSysvolDFSRSplat | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
$Executed = Invoke-CimMethod -InputObject $_.DFSR -MethodName 'cleanupconflictdirectory' -CimSession $_.ComputerName
|
||||
if ($Executed) {
|
||||
[PSCustomObject] @{
|
||||
Status = $StatusCodes["$($Executed.ReturnValue)"]
|
||||
ComputerName = $Executed.PSComputerName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
function ConvertFrom-CSExtension {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string[]] $CSE,
|
||||
[switch] $Limited
|
||||
)
|
||||
$GUIDs = @{
|
||||
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpreg/f0dba6b8-704f-45d5-999f-1a0a694a6df9
|
||||
'{35378EAC-683F-11D2-A89A-00C04FBBCFA2}' = 'Client-side extension GUID (CSE GUID)'
|
||||
'{0F6B957E-509E-11D1-A7CC-0000F87571E3}' = 'Tool Extension GUID (User Policy Settings)'
|
||||
'{D02B1F73-3407-48AE-BA88-E8213C6761F1}' = 'Tool Extension GUID (User Policy Settings)'
|
||||
'{0F6B957D-509E-11D1-A7CC-0000F87571E3}' = 'Tool Extension GUID (Computer Policy Settings)'
|
||||
'{D02B1F72-3407-48AE-BA88-E8213C6761F1}' = 'Tool Extension GUID (Computer Policy Settings)'
|
||||
'{0ACDD40C-75AC-47ab-BAA0-BF6DE7E7FE63}' = 'Wireless Group Policy'
|
||||
'{0E28E245-9368-4853-AD84-6DA3BA35BB75}' = 'Group Policy Environment'
|
||||
'{16be69fa-4209-4250-88cb-716cf41954e0}' = 'Central Access Policy Configuration'
|
||||
'{17D89FEC-5C44-4972-B12D-241CAEF74509}' = 'Group Policy Local Users and Groups'
|
||||
'{1A6364EB-776B-4120-ADE1-B63A406A76B5}' = 'Group Policy Device Settings'
|
||||
'{25537BA6-77A8-11D2-9B6C-0000F8080861}' = 'Folder Redirection'
|
||||
'{2A8FDC61-2347-4C87-92F6-B05EB91A201A}' = 'MitigationOptions'
|
||||
'{346193F5-F2FD-4DBD-860C-B88843475FD3}' = 'ConfigMgr User State Management Extension.'
|
||||
'{3610eda5-77ef-11d2-8dc5-00c04fa31a66}' = 'Microsoft Disk Quota'
|
||||
'{3A0DBA37-F8B2-4356-83DE-3E90BD5C261F}' = 'Group Policy Network Options'
|
||||
'{426031c0-0b47-4852-b0ca-ac3d37bfcb39}' = 'QoS Packet Scheduler'
|
||||
'{42B5FAAE-6536-11d2-AE5A-0000F87571E3}' = 'Scripts'
|
||||
'{4bcd6cde-777b-48b6-9804-43568e23545d}' = 'Remote Desktop USB Redirection'
|
||||
'{4CFB60C1-FAA6-47f1-89AA-0B18730C9FD3}' = 'Internet Explorer Zonemapping'
|
||||
'{4D2F9B6F-1E52-4711-A382-6A8B1A003DE6}' = 'RADCProcessGroupPolicyEx'
|
||||
'{4d968b55-cac2-4ff5-983f-0a54603781a3}' = 'Work Folders'
|
||||
'{5794DAFD-BE60-433f-88A2-1A31939AC01F}' = 'Group Policy Drive Maps'
|
||||
'{6232C319-91AC-4931-9385-E70C2B099F0E}' = 'Group Policy Folders'
|
||||
'{6A4C88C6-C502-4f74-8F60-2CB23EDC24E2}' = 'Group Policy Network Shares'
|
||||
'{7150F9BF-48AD-4da4-A49C-29EF4A8369BA}' = 'Group Policy Files'
|
||||
'{728EE579-943C-4519-9EF7-AB56765798ED}' = 'Group Policy Data Sources'
|
||||
'{74EE6C03-5363-4554-B161-627540339CAB}' = 'Group Policy Ini Files'
|
||||
'{7933F41E-56F8-41d6-A31C-4148A711EE93}' = 'Windows Search Group Policy Extension'
|
||||
'{7B849a69-220F-451E-B3FE-2CB811AF94AE}' = 'Internet Explorer User Accelerators'
|
||||
'{827D319E-6EAC-11D2-A4EA-00C04F79F83A}' = 'Security'
|
||||
'{8A28E2C5-8D06-49A4-A08C-632DAA493E17}' = 'Deployed Printer Connections'
|
||||
'{91FBB303-0CD5-4055-BF42-E512A681B325}' = 'Group Policy Services'
|
||||
'{A3F3E39B-5D83-4940-B954-28315B82F0A8}' = 'Group Policy Folder Options'
|
||||
'{AADCED64-746C-4633-A97C-D61349046527}' = 'Group Policy Scheduled Tasks'
|
||||
'{B087BE9D-ED37-454f-AF9C-04291E351182}' = 'Group Policy Registry'
|
||||
'{B587E2B1-4D59-4e7e-AED9-22B9DF11D053}' = '802.3 Group Policy'
|
||||
'{BA649533-0AAC-4E04-B9BC-4DBAE0325B12}' = 'Windows To Go Startup Options'
|
||||
'{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}' = 'Group Policy Printers'
|
||||
'{C34B2751-1CF4-44F5-9262-C3FC39666591}' = 'Windows To Go Hibernate Options'
|
||||
'{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}' = 'Group Policy Shortcuts'
|
||||
'{C631DF4C-088F-4156-B058-4375F0853CD8}' = 'Microsoft Offline Files'
|
||||
'{c6dc5466-785a-11d2-84d0-00c04fb169f7}' = 'Software Installation'
|
||||
'{cdeafc3d-948d-49dd-ab12-e578ba4af7aa}' = 'TCPIP'
|
||||
'{CF7639F3-ABA2-41DB-97F2-81E2C5DBFC5D}' = 'Internet Explorer Machine Accelerators'
|
||||
'{e437bc1c-aa7d-11d2-a382-00c04f991e27}' = 'IP Security'
|
||||
'{E47248BA-94CC-49c4-BBB5-9EB7F05183D0}' = 'Group Policy Internet Settings'
|
||||
'{E4F48E54-F38D-4884-BFB9-D4D2E5729C18}' = 'Group Policy Start Menu Settings'
|
||||
'{E5094040-C46C-4115-B030-04FB2E545B00}' = 'Group Policy Regional Options'
|
||||
'{E62688F0-25FD-4c90-BFF5-F508B9D2E31F}' = 'Group Policy Power Options'
|
||||
'{F312195E-3D9D-447A-A3F5-08DFFA24735E}' = 'ProcessVirtualizationBasedSecurityGroupPolicy'
|
||||
'{f3ccc681-b74c-4060-9f26-cd84525dca2a}' = 'Audit Policy Configuration'
|
||||
'{F9C77450-3A41-477E-9310-9ACD617BD9E3}' = 'Group Policy Applications'
|
||||
'{FB2CA36D-0B40-4307-821B-A13B252DE56C}' = 'Enterprise QoS'
|
||||
'{fbf687e6-f063-4d9f-9f4f-fd9a26acdd5f}' = 'CP'
|
||||
'{FC491EF1-C4AA-4CE1-B329-414B101DB823}' = 'ProcessConfigCIPolicyGroupPolicy'
|
||||
'{169EBF44-942F-4C43-87CE-13C93996EBBE}' = 'UEV Policy'
|
||||
'{2BFCC077-22D2-48DE-BDE1-2F618D9B476D}' = 'AppV Policy'
|
||||
'{4B7C3B0F-E993-4E06-A241-3FBE06943684}' = 'Per-process Mitigation Options'
|
||||
'{7909AD9E-09EE-4247-BAB9-7029D5F0A278}' = 'MDM Policy'
|
||||
'{CFF649BD-601D-4361-AD3D-0FC365DB4DB7}' = 'Delivery Optimization GP extension'
|
||||
'{D76B9641-3288-4f75-942D-087DE603E3EA}' = 'AdmPwd'
|
||||
'{9650FDBC-053A-4715-AD14-FC2DC65E8330}' = 'Unknown'
|
||||
'{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}' = 'EFS Recovery'
|
||||
'{A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B}' = 'Internet Explorer Maintenance Policy Processing'
|
||||
'{FC715823-C5FB-11D1-9EEF-00A0C90347FF}' = 'Internet Explorer Maintenance Extension Protocol' # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpie/f566a58a-4114-4981-b1e2-30b9d1a3c0e6
|
||||
}
|
||||
foreach ($C in $CSE) {
|
||||
if (-not $Limited) {
|
||||
if ($GUIDs[$C]) {
|
||||
[PSCustomObject] @{ Name = $C; Description = $GUIDs[$C] }
|
||||
} else {
|
||||
[PSCustomObject] @{ Name = $C; Description = $C }
|
||||
}
|
||||
} else {
|
||||
if ($GUIDs[$C]) {
|
||||
$GUIDs[$C]
|
||||
} else {
|
||||
$CSE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
function Find-CSExtension {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string[]] $CSE,
|
||||
[string] $ComputerName
|
||||
)
|
||||
#List Group Policy Client Side Extensions, CSEs, from Windows 10
|
||||
$Keys = Get-PSRegistry -RegistryPath "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions" -ComputerName $ComputerName
|
||||
foreach ($Key in $Keys.PSSubKeys) {
|
||||
$RegistryKey = Get-PSRegistry -RegistryPath "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions\$Key" -ComputerName $ComputerName
|
||||
if ($CSE) {
|
||||
foreach ($C in $CSE) {
|
||||
if ($RegistryKey.DefaultKey -eq $Key) {
|
||||
[PSCustomObject] @{ Name = $Key; Description = $RegistryKey.DefaultKey }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] @{ CSE = $Key; Description = $RegistryKey.DefaultKey }
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-6
@@ -29,9 +29,13 @@
|
||||
if (-not $GPOPath) {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$QueryServer = $ForestInformation.QueryServers[$Domain]['HostName'][0]
|
||||
$Count = 0
|
||||
if ($GPOName) {
|
||||
Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
$GroupPolicies = Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
if (-not $Limited) {
|
||||
try {
|
||||
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
|
||||
@@ -45,8 +49,11 @@
|
||||
}
|
||||
}
|
||||
} elseif ($GPOGuid) {
|
||||
Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
$GroupPolicies = Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
if (-not $Limited) {
|
||||
try {
|
||||
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
|
||||
@@ -60,8 +67,11 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
$GroupPolicies = Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
if (-not $Limited) {
|
||||
try {
|
||||
$XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
|
||||
@@ -78,11 +88,13 @@
|
||||
}
|
||||
} else {
|
||||
foreach ($Path in $GPOPath) {
|
||||
Write-Verbose "Get-GPOZaurr - Getting GPO content from XML files"
|
||||
Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml | ForEach-Object {
|
||||
$XMLContent = [XML]::new()
|
||||
$XMLContent.Load($_.FullName)
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent
|
||||
}
|
||||
Write-Verbose "Get-GPOZaurr - Finished GPO content from XML files"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
function Get-GPOZaurrBroken {
|
||||
[alias('Get-GPOZaurrSysvol')]
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[string[]] $ExcludeDomainControllers,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
|
||||
[switch] $SkipRODC,
|
||||
[Array] $GPOs,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $VerifyDomainControllers
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeDomainControllers $ExcludeDomainControllers -IncludeDomainControllers $IncludeDomainControllers -SkipRODC:$SkipRODC -ExtendedForestInformation $ExtendedForestInformation -Extended
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$TimeLog = Start-TimeLog
|
||||
Write-Verbose "Get-GPOZaurrBroken - Starting process for $Domain"
|
||||
$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
|
||||
$SystemsContainer = $ForestInformation['DomainsExtended'][$Domain].SystemsContainer
|
||||
$PoliciesAD = @{}
|
||||
if ($SystemsContainer) {
|
||||
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
|
||||
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer
|
||||
foreach ($Policy in $PoliciesInAD) {
|
||||
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
|
||||
$GUIDFromDN = $GUIDFromDN -replace '{' -replace '}'
|
||||
$GUID = $Policy.Name -replace '{' -replace '}'
|
||||
if ($GUID -and $GUIDFromDN) {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Exists'
|
||||
} else {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Permissions issue'
|
||||
}
|
||||
}
|
||||
}
|
||||
Try {
|
||||
[Array]$GPOs = Get-GPO -All -Domain $Domain -Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Error: $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
if ($GPOs.Count -ge 2) {
|
||||
if (-not $VerifyDomainControllers) {
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Domain -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
} else {
|
||||
foreach ($Server in $ForestInformation['DomainDomainControllers']["$Domain"]) {
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing $Domain \ $($Server.HostName.Trim())"
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Server.Hostname -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurrBroken - GPO count for $Domain is less then 2. This is not expected for fully functioning domain. Skipping processing SYSVOL folder."
|
||||
}
|
||||
$TimeEnd = Stop-TimeLog -Time $TimeLog -Option OneLiner
|
||||
Write-Verbose "Get-GPOZaurrBroken - Finishing process for $Domain (Time to process: $TimeEnd)"
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
function Get-GPOZaurrEmptyFolders {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $AllFolders
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
Get-ChildItem -Path "\\$Domain\SYSVOL\$Domain\policies" -ErrorAction SilentlyContinue -Recurse -ErrorVariable err -Force -Directory | ForEach-Object {
|
||||
$FullFolder = Test-Path -Path "$($_.FullName)\*"
|
||||
if (-not $FullFolder -or $AllFolders) {
|
||||
[PSCustomObject] @{
|
||||
FullName = $_.FullName
|
||||
IsEmptyFolder = -not $FullFolder
|
||||
Name = $_.Name
|
||||
Root = $_.Root
|
||||
Parent = $_.Parent
|
||||
CreationTime = $_.CreationTime
|
||||
LastWriteTime = $_.LastWriteTime
|
||||
Attributes = $_.Attributes
|
||||
DomainName = $Domain
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
|
||||
[ValidateSet('None', 'MACTripleDES', 'MD5', 'RIPEMD160', 'SHA1', 'SHA256', 'SHA384', 'SHA512')][string] $HashAlgorithm = 'None',
|
||||
[switch] $Signature,
|
||||
[switch] $Limited,
|
||||
[switch] $AsHashTable,
|
||||
[switch] $Extended,
|
||||
[switch] $ExtendedMetaData,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
@@ -50,6 +50,9 @@
|
||||
"\\$Domain\NETLOGON" = @{
|
||||
Name = 'NETLOGON Scripts'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain\DfsrPrivate" = @{
|
||||
Name = 'DfsrPrivate'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain" = @{
|
||||
Name = 'SYSVOL Root'
|
||||
}
|
||||
@@ -262,7 +265,7 @@
|
||||
$SuggestedAction = 'Requires verification'
|
||||
$SuggestedActionComment = 'Not able to auto asses'
|
||||
}
|
||||
if ($Limited) {
|
||||
if (-not $ExtendedMetaData) {
|
||||
$MetaData = [ordered] @{
|
||||
LocationType = $FileType.Name
|
||||
FullName = $_.FullName
|
||||
@@ -279,18 +282,39 @@
|
||||
}
|
||||
} else {
|
||||
$MetaData = Get-FileMetaData -File $_ -AsHashTable
|
||||
$MetaData['SuggestedAction'] = $SuggestedAction
|
||||
$MetaData['SuggestedActionComment'] = $SuggestedActionComment
|
||||
$MetaData['BelongsToGPO'] = $BelongsToGPO
|
||||
$MetaData['GPODisplayName'] = $GPODisplayName
|
||||
}
|
||||
if ($Signature) {
|
||||
$DigitalSignature = Get-AuthenticodeSignature -FilePath $_.Fullname
|
||||
$MetaData['SignatureStatus'] = $DigitalSignature.Status
|
||||
$MetaData['IsOSBinary'] = $DigitalSignature.IsOSBinary
|
||||
$MetaData['SignatureCertificateSubject'] = $DigitalSignature.SignerCertificate.Subject
|
||||
if ($Extended) {
|
||||
$MetaData['SignatureCertificateIssuer'] = $DigitalSignature.SignerCertificate.Issuer
|
||||
$MetaData['SignatureCertificateSerialNumber'] = $DigitalSignature.SignerCertificate.SerialNumber
|
||||
$MetaData['SignatureCertificateNotBefore'] = $DigitalSignature.SignerCertificate.NotBefore
|
||||
$MetaData['SignatureCertificateNotAfter'] = $DigitalSignature.SignerCertificate.NotAfter
|
||||
$MetaData['SignatureCertificateThumbprint'] = $DigitalSignature.SignerCertificate.Thumbprint
|
||||
try {
|
||||
$DigitalSignature = Get-AuthenticodeSignature -FilePath $_.Fullname -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrFiles - Error when reading signature: $($_.Exception.Message)"
|
||||
}
|
||||
if ($DigitalSignature) {
|
||||
$MetaData['SignatureStatus'] = $DigitalSignature.Status
|
||||
$MetaData['IsOSBinary'] = $DigitalSignature.IsOSBinary
|
||||
$MetaData['SignatureCertificateSubject'] = $DigitalSignature.SignerCertificate.Subject
|
||||
if ($Extended) {
|
||||
$MetaData['SignatureCertificateIssuer'] = $DigitalSignature.SignerCertificate.Issuer
|
||||
$MetaData['SignatureCertificateSerialNumber'] = $DigitalSignature.SignerCertificate.SerialNumber
|
||||
$MetaData['SignatureCertificateNotBefore'] = $DigitalSignature.SignerCertificate.NotBefore
|
||||
$MetaData['SignatureCertificateNotAfter'] = $DigitalSignature.SignerCertificate.NotAfter
|
||||
$MetaData['SignatureCertificateThumbprint'] = $DigitalSignature.SignerCertificate.Thumbprint
|
||||
}
|
||||
} else {
|
||||
$MetaData['SignatureStatus'] = 'Not available'
|
||||
$MetaData['IsOSBinary'] = $null
|
||||
$MetaData['SignatureCertificateSubject'] = $null
|
||||
if ($Extended) {
|
||||
$MetaData['SignatureCertificateIssuer'] = $null
|
||||
$MetaData['SignatureCertificateSerialNumber'] = $null
|
||||
$MetaData['SignatureCertificateNotBefore'] = $null
|
||||
$MetaData['SignatureCertificateNotAfter'] = $null
|
||||
$MetaData['SignatureCertificateThumbprint'] = $null
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($HashAlgorithm -ne 'None') {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
function Get-GPOZaurrFilesPolicyDefinitions {
|
||||
function Get-GPOZaurrFilesPolicyDefinition {
|
||||
[alias('Get-GPOZaurrFilesPolicyDefinitions')]
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
@@ -55,7 +56,7 @@ function Get-GPOZaurrFilesPolicyDefinitions {
|
||||
if ($FilesCache[$Domain][$FileLanguage.BaseName]) {
|
||||
$FilesCache[$Domain][$FileLanguage.BaseName][$Directory.Name] = $true
|
||||
} else {
|
||||
#Write-Warning "Get-GPOZaurrFilesPolicyDefinitions - File $($FileLanguage.FullName) doesn't have a match."
|
||||
#Write-Warning "Get-GPOZaurrFilesPolicyDefinition - File $($FileLanguage.FullName) doesn't have a match."
|
||||
$Output.FilesToDelete.Add(
|
||||
[PSCustomobject] @{
|
||||
Name = $FileLanguage.BaseName
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
function Get-GPOZaurrFolders {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
|
||||
[ValidateSet('All', 'NTFRS', 'Empty')][string] $FolderType = 'All',
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $AsHashTable
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$Path = @(
|
||||
if ($Type -contains 'All') {
|
||||
"\\$Domain\SYSVOL\$Domain"
|
||||
}
|
||||
if ($Type -contains 'Sysvol') {
|
||||
"\\$Domain\SYSVOL\$Domain\policies"
|
||||
}
|
||||
if ($Type -contains 'NetLogon') {
|
||||
"\\$Domain\NETLOGON"
|
||||
}
|
||||
)
|
||||
# Order does matter
|
||||
$Folders = [ordered] @{
|
||||
"\\$Domain\SYSVOL\$Domain\policies\PolicyDefinitions" = @{
|
||||
Name = 'SYSVOL PolicyDefinitions'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain\policies" = @{
|
||||
Name = 'SYSVOL Policies'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain\scripts" = @{
|
||||
Name = 'NETLOGON Scripts'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain\StarterGPOs" = @{
|
||||
Name = 'SYSVOL GPO Starters'
|
||||
}
|
||||
"\\$Domain\NETLOGON" = @{
|
||||
Name = 'NETLOGON Scripts'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain\DfsrPrivate" = @{
|
||||
Name = 'DfsrPrivate'
|
||||
}
|
||||
"\\$Domain\SYSVOL\$Domain" = @{
|
||||
Name = 'SYSVOL Root'
|
||||
}
|
||||
}
|
||||
$Exclusions = @{
|
||||
DfsrPrivate = @{
|
||||
ConflictAndDeleted = $true
|
||||
Deleted = $true
|
||||
Installing = $true
|
||||
}
|
||||
'SYSVOL Policies' = @{
|
||||
User = $true
|
||||
Machine = $true
|
||||
}
|
||||
'NETLOGON Scripts' = @{
|
||||
|
||||
}
|
||||
'SYSVOL Root' = @{
|
||||
|
||||
}
|
||||
'SYSVOL GPO Starters' = @{
|
||||
|
||||
}
|
||||
'SYSVOL PolicyDefinitions' = @{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Get-ChildItem -Path $Path -ErrorAction SilentlyContinue -Recurse -ErrorVariable +err -Force -Directory | ForEach-Object {
|
||||
$FileType = foreach ($Key in $Folders.Keys) {
|
||||
if ($_.FullName -like "$Key*") {
|
||||
$Folders[$Key]
|
||||
break
|
||||
}
|
||||
}
|
||||
$RootFolder = $Folders["$($_.FullName)"]
|
||||
if ($RootFolder) {
|
||||
$IsRootFolder = $true
|
||||
} else {
|
||||
$IsRootFolder = $false
|
||||
}
|
||||
|
||||
$IsExcluded = $Exclusions["$($FileType.Name)"]["$($_.Name)"] -is [bool]
|
||||
if ($IsRootFolder -and $IsExcluded -eq $false) {
|
||||
$IsExcluded = $true
|
||||
}
|
||||
|
||||
$FullFolder = Test-Path -Path "$($_.FullName)\*"
|
||||
$BrokenReplicationRoot = $_.Name -like '*_NTFRS_*'
|
||||
$BrokenReplicationChild = $_.FullName -like '*_NTFRS_*' -and $_.Name -notlike '*_NTFRS_*'
|
||||
$BrokenReplication = $_.FullName -like '*_NTFRS_*'
|
||||
|
||||
$Object = [ordered] @{
|
||||
FolderType = $FileType.Name
|
||||
FullName = $_.FullName
|
||||
IsEmptyFolder = -not $FullFolder
|
||||
IsBrokenReplication = $BrokenReplication
|
||||
IsBrokenReplicationRoot = $BrokenReplicationRoot
|
||||
IsBrokenReplicationChild = $BrokenReplicationChild
|
||||
IsRootFolder = $IsRootFolder
|
||||
IsExcluded = $IsExcluded
|
||||
Name = $_.Name
|
||||
Root = $_.Root
|
||||
Parent = $_.Parent
|
||||
CreationTime = $_.CreationTime
|
||||
LastWriteTime = $_.LastWriteTime
|
||||
Attributes = $_.Attributes
|
||||
DomainName = $Domain
|
||||
}
|
||||
if (-not $Object.IsExcluded) {
|
||||
if ($FolderType -eq 'Empty' -and $Object.IsEmptyFolder -eq $true) {
|
||||
if ($AsHashTable) {
|
||||
$Object
|
||||
} else {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
} elseif ($FolderType -eq 'NTFRS' -and $Object.IsBrokenReplicationRoot -eq $true) {
|
||||
if ($AsHashTable) {
|
||||
$Object
|
||||
} else {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
} elseif ($FolderType -eq 'All') {
|
||||
if ($AsHashTable) {
|
||||
$Object
|
||||
} else {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($e in $err) {
|
||||
Write-Warning "Get-GPOZaurrFolders - $($e.Exception.Message) ($($e.CategoryInfo.Reason))"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
function Get-GPOZaurrInheritance {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[switch] $IncludeBlockedObjects,
|
||||
[switch] $OnlyBlockedInheritance,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
Begin {
|
||||
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
Process {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$OrganizationalUnits = Get-ADOrganizationalUnit -Filter * -Properties gpOptions, canonicalName -Server $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
foreach ($OU in $OrganizationalUnits) {
|
||||
$InheritanceInformation = [Ordered] @{
|
||||
CanonicalName = $OU.canonicalName
|
||||
BlockedInheritance = if ($OU.gpOptions -eq 1) { $true } else { $false }
|
||||
}
|
||||
if (-not $IncludeBlockedObjects) {
|
||||
if ($OnlyBlockedInheritance) {
|
||||
if ($InheritanceInformation.BlockedInheritance -eq $true) {
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
}
|
||||
} else {
|
||||
if ($InheritanceInformation) {
|
||||
if ($InheritanceInformation.BlockedInheritance -eq $true) {
|
||||
$InheritanceInformation['UsersCount'] = $null
|
||||
$InheritanceInformation['ComputersCount'] = $null
|
||||
[Array] $InheritanceInformation['Users'] = (Get-ADUser -SearchBase $OU.DistinguishedName -Server $ForestInformation['QueryServers'][$Domain]['HostName'][0] -Filter *).SamAccountName
|
||||
[Array] $InheritanceInformation['Computers'] = (Get-ADComputer -SearchBase $OU.DistinguishedName -Server $ForestInformation['QueryServers'][$Domain]['HostName'][0] -Filter *).SamAccountName
|
||||
$InheritanceInformation['UsersCount'] = $InheritanceInformation['Users'].Count
|
||||
$InheritanceInformation['ComputersCount'] = $InheritanceInformation['Computers'].Count
|
||||
} else {
|
||||
$InheritanceInformation['UsersCount'] = $null
|
||||
$InheritanceInformation['ComputersCount'] = $null
|
||||
$InheritanceInformation['Users'] = $null
|
||||
$InheritanceInformation['Computers'] = $null
|
||||
}
|
||||
}
|
||||
if ($OnlyBlockedInheritance) {
|
||||
if ($InheritanceInformation.BlockedInheritance -eq $true) {
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
}
|
||||
}
|
||||
$InheritanceInformation['DistinguishedName'] = $OU.DistinguishedName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
|
||||
$OrganizationalUnits = Get-ADOrganizationalUnit -Filter *
|
||||
$Output = foreach ($OU in $OrganizationalUnits) {
|
||||
Get-GPInheritance -Target $OU.DistinguishedName
|
||||
}
|
||||
$Output | Format-Table
|
||||
#>
|
||||
@@ -0,0 +1,70 @@
|
||||
function Get-GPOZaurrNetLogon {
|
||||
[cmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param(
|
||||
[parameter(ParameterSetName = 'OwnerOnly')][switch] $OwnerOnly,
|
||||
[parameter(ParameterSetName = 'SkipOwner')][switch] $SkipOwner
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Extended
|
||||
$FilesAll = foreach ($Domain in $ForestInformation.Domains) {
|
||||
$Path = -join ("\\", $Domain, '\Netlogon')
|
||||
$Files = Get-ChildItem -LiteralPath $Path -Recurse
|
||||
foreach ($_ in $Files) {
|
||||
$ACL = Get-Acl -Path $_.FullName
|
||||
if ($ACL.Owner) {
|
||||
$IdentityOwner = Convert-Identity -Identity $ACL.Owner
|
||||
} else {
|
||||
$IdentityOwner = [PSCustomObject] @{ SID = ''; Type = 'Uknown' }
|
||||
}
|
||||
if (-not $OwnerOnly) {
|
||||
if (-not $SkipOwner) {
|
||||
[PSCustomObject] @{
|
||||
FullName = $_.FullName
|
||||
Extension = $_.Extension
|
||||
CreationTime = $_.CreationTime
|
||||
LastAccessTime = $_.LastAccessTime
|
||||
LastWriteTime = $_.LastWriteTime
|
||||
Attributes = $_.Attributes
|
||||
AccessControlType = 'Allow' # : Allow
|
||||
Principal = $IdentityOwner.Name # : BUILTIN\Administrators
|
||||
PrincipalSid = $IdentityOwner.SID
|
||||
PrincipalType = $IdentityOwner.Type
|
||||
FileSystemRights = 'Owner' # : FullControl
|
||||
IsInherited = $false
|
||||
#Owner = $ACL.Owner
|
||||
}
|
||||
}
|
||||
$FilePermission = Get-FilePermissions -Path $_.FullName -ACLS $ACL
|
||||
foreach ($Perm in $FilePermission) {
|
||||
$Identity = Convert-Identity -Identity $Perm.Principal
|
||||
[PSCustomObject] @{
|
||||
FullName = $_.FullName
|
||||
Extension = $_.Extension
|
||||
CreationTime = $_.CreationTime
|
||||
LastAccessTime = $_.LastAccessTime
|
||||
LastWriteTime = $_.LastWriteTime
|
||||
Attributes = $_.Attributes
|
||||
AccessControlType = $Perm.AccessControlType # : Allow
|
||||
Principal = $Identity.Name # : BUILTIN\Administrators
|
||||
PrincipalSid = $Identity.SID
|
||||
PrincipalType = $Identity.Type
|
||||
FileSystemRights = $Perm.FileSystemRights # : FullControl
|
||||
IsInherited = $Perm.IsInherited # : True
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] @{
|
||||
FullName = $_.FullName
|
||||
Extension = $_.Extension
|
||||
CreationTime = $_.CreationTime
|
||||
LastAccessTime = $_.LastAccessTime
|
||||
LastWriteTime = $_.LastWriteTime
|
||||
Attributes = $_.Attributes
|
||||
Owner = $IdentityOwner.Name
|
||||
OwnerSid = $IdentityOwner.SID
|
||||
OwnerType = $IdentityOwner.Type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$FilesAll
|
||||
}
|
||||
@@ -49,6 +49,9 @@
|
||||
$Object['SysvolType'] = $FileOwner.OwnerType
|
||||
$Object['SysvolPath'] = $_.Path
|
||||
$Object['IsOwnerConsistent'] = if ($ACL.OwnerName -eq $FileOwner.OwnerName) { $true } else { $false }
|
||||
$Object['IsOwnerAdministrative'] = if ($Object['SysvolType'] -eq 'Administrative' -and $Object['OwnerType'] -eq 'Administrative') { $true } else { $false }
|
||||
} else {
|
||||
$Object['IsOwnerAdministrative'] = if ($Object['OwnerType'] -eq 'Administrative') { $true } else { $false }
|
||||
}
|
||||
$Object['DistinguishedName'] = $_.GPODistinguishedName
|
||||
[PSCUstomObject] $Object
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
[alias('GUID', 'GPOID')][string] $GPOGuid,
|
||||
|
||||
[string[]] $Principal,
|
||||
[validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
[validateset('DistinguishedName', 'Name', 'NetbiosName', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
|
||||
[validateSet('AuthenticatedUsers', 'DomainComputers', 'Unknown', 'WellKnownAdministrative', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All')][string[]] $Type = 'All',
|
||||
|
||||
[switch] $SkipWellKnown,
|
||||
[switch] $SkipAdministrative,
|
||||
[switch] $ResolveAccounts,
|
||||
#[switch] $ResolveAccounts,
|
||||
|
||||
[switch] $IncludeOwner,
|
||||
[Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType,
|
||||
@@ -43,6 +43,7 @@
|
||||
Write-Warning "Get-GPOZaurrPermission - Using SkipAdministrative or SkipWellKnown while looking for Unknown doesn't make sense as only Unknown will be displayed."
|
||||
}
|
||||
}
|
||||
<#
|
||||
if ($ResolveAccounts) {
|
||||
$Accounts = @{ }
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
@@ -60,6 +61,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
||||
Process {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
@@ -96,7 +98,7 @@
|
||||
Principal = $Principal
|
||||
PrincipalType = $PrincipalType
|
||||
PermitType = $PermitType
|
||||
Accounts = $Accounts
|
||||
#Accounts = $Accounts
|
||||
Type = $Type
|
||||
GPO = $_
|
||||
SkipWellKnown = $SkipWellKnown.IsPresent
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
}
|
||||
Process {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$TimeLog = Start-TimeLog
|
||||
Write-Verbose "Get-GPOZaurrPermissionConsistency - Starting process for $Domain"
|
||||
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
if ($GPOName) {
|
||||
$getGPOSplat = @{
|
||||
@@ -39,30 +41,36 @@
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
}
|
||||
Get-GPO @getGPOSplat | ForEach-Object -Process {
|
||||
$GroupPolicies = Get-GPO @getGPOSplat
|
||||
$Count = 0
|
||||
$GroupPolicies | ForEach-Object -Process {
|
||||
$Count++
|
||||
Write-Verbose "Get-GPOZaurrPermissionConsistency - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
try {
|
||||
$IsConsistent = $_.IsAclConsistent()
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)."
|
||||
$IsConsistent = 'Not available.'
|
||||
$IsConsistent = 'Not available'
|
||||
}
|
||||
$SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $_.ID.GUID, '}')
|
||||
if ($VerifyInheritance) {
|
||||
$FolderPermissions = Get-WinADSharePermission -Path $SysVolpath
|
||||
[Array] $NotInheritedPermissions = foreach ($File in $FolderPermissions) {
|
||||
if ($File.Path -ne $SysVolpath -and $File.IsInherited -eq $false) {
|
||||
$File
|
||||
$FolderPermissions = Get-WinADSharePermission -Path $SysVolpath -Verbose:$false
|
||||
if ($FolderPermissions) {
|
||||
[Array] $NotInheritedPermissions = foreach ($File in $FolderPermissions) {
|
||||
if ($File.Path -ne $SysVolpath -and $File.IsInherited -eq $false) {
|
||||
$File
|
||||
}
|
||||
}
|
||||
if ($NotInheritedPermissions.Count -eq 0) {
|
||||
$ACLConsistentInside = $true
|
||||
} else {
|
||||
$ACLConsistentInside = $false
|
||||
}
|
||||
}
|
||||
if ($NotInheritedPermissions.Count -eq 0) {
|
||||
$ACLConsistentInside = $true
|
||||
} else {
|
||||
$ACLConsistentInside = $false
|
||||
$ACLConsistentInside = 'Not available'
|
||||
}
|
||||
} else {
|
||||
$ACLConsistentInside = $null
|
||||
}
|
||||
$Object = [ordered] @{
|
||||
DisplayName = $_.DisplayName # : New Group Policy Object
|
||||
@@ -94,26 +102,28 @@
|
||||
[PSCustomObject] $Object
|
||||
} elseif ($Type -eq 'Inconsistent') {
|
||||
if ($VerifyInheritance) {
|
||||
if (-not $IsConsistent -or -not $ACLConsistentInside) {
|
||||
if (-not ($IsConsistent -eq $true) -or (-not $ACLConsistentInside -eq $true)) {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
} else {
|
||||
if (-not $IsConsistent) {
|
||||
if (-not ($IsConsistent -eq $true)) {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
}
|
||||
} elseif ($Type -eq 'Consistent') {
|
||||
if ($VerifyInheritance) {
|
||||
if ($IsConsistent -and $ACLConsistentInside) {
|
||||
if ($IsConsistent -eq $true -and $ACLConsistentInside -eq $true) {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
} else {
|
||||
if ($IsConsistent) {
|
||||
if ($IsConsistent -eq $true) {
|
||||
[PSCustomObject] $Object
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$TimeEnd = Stop-TimeLog -Time $TimeLog -Option OneLiner
|
||||
Write-Verbose "Get-GPOZaurrPermissionConsistency - Finishing process for $Domain (Time to process: $TimeEnd)"
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
function Get-GPOZaurrPermissionRoot {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('GpoRootCreate', 'GpoRootOwner')][string[]] $IncludePermissionType,
|
||||
[ValidateSet('GpoRootCreate', 'GpoRootOwner')][string[]] $ExcludePermissionType,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
Begin {
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Extended
|
||||
}
|
||||
Process {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain].DistinguishedName
|
||||
$QueryServer = $ForestInformation['QueryServers'][$Domain].HostName[0]
|
||||
$getADACLSplat = @{
|
||||
ADObject = "CN=Policies,CN=System,$DomainDistinguishedName"
|
||||
IncludeActiveDirectoryRights = 'GenericAll', 'CreateChild', 'WriteOwner', 'WriteDACL'
|
||||
IncludeObjectTypeName = 'All', 'Group-Policy-Container'
|
||||
IncludeInheritedObjectTypeName = 'All', 'Group-Policy-Container'
|
||||
ADRightsAsArray = $true
|
||||
ResolveTypes = $true
|
||||
}
|
||||
$GPOPermissionsGlobal = Get-ADACL @getADACLSplat -Verbose:$false
|
||||
$GPOs = Get-ADObject -SearchBase "CN=Policies,CN=System,$DomainDistinguishedName" -SearchScope OneLevel -Filter * -Properties DisplayName -Server $QueryServer -Verbose:$false
|
||||
foreach ($Permission in $GPOPermissionsGlobal) {
|
||||
$CustomPermission = foreach ($_ in $Permission.ActiveDirectoryRights) {
|
||||
if ($_ -in 'WriteDACL', 'WriteOwner', 'GenericAll' ) {
|
||||
'GpoRootOwner'
|
||||
}
|
||||
if ($_ -in 'CreateChild', 'GenericAll') {
|
||||
'GpoRootCreate'
|
||||
}
|
||||
}
|
||||
$CustomPermission = $CustomPermission | Sort-Object -Unique
|
||||
foreach ($SinglePermission in $CustomPermission) {
|
||||
if ($SinglePermission -in $ExcludePermissionType) {
|
||||
continue
|
||||
}
|
||||
if ($IncludePermissionType.Count -gt 0 -and $SinglePermission -notin $IncludePermissionType) {
|
||||
continue
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
PrincipalName = $Permission.Principal
|
||||
Permission = $SinglePermission
|
||||
PermissionType = $Permission.AccessControlType
|
||||
PrincipalSidType = $Permission.PrincipalType
|
||||
PrincipalObjectClass = $Permission.PrincipalObjectType
|
||||
PrincipalDomainName = $Permission.PrincipalObjectDomain
|
||||
PrincipalSid = $Permission.PrincipalObjectSid
|
||||
GPOCount = $GPOs.Count
|
||||
GPONames = $GPOs.DisplayName
|
||||
DomainName = $Domain
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End {}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
function Get-GPOZaurrPermissionSummary {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[validateSet('AuthenticatedUsers', 'DomainComputers', 'Unknown', 'WellKnownAdministrative', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All')][string[]] $Type = 'All',
|
||||
[validateSet('Allow', 'Deny', 'All')][string] $PermitType = 'All',
|
||||
[ValidateSet('GpoApply', 'GpoEdit', 'GpoCustom', 'GpoEditDeleteModifySecurity', 'GpoRead', 'GpoOwner', 'GpoRootCreate', 'GpoRootOwner')][string[]] $IncludePermissionType,
|
||||
[ValidateSet('GpoApply', 'GpoEdit', 'GpoCustom', 'GpoEditDeleteModifySecurity', 'GpoRead', 'GpoOwner', 'GpoRootCreate', 'GpoRootOwner')][string[]] $ExcludePermissionType,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
|
||||
[string] $Separator
|
||||
)
|
||||
|
||||
$IncludePermTypes = [System.Collections.Generic.List[Microsoft.GroupPolicy.GPPermissionType]]::new()
|
||||
$ExcludePermTypes = [System.Collections.Generic.List[Microsoft.GroupPolicy.GPPermissionType]]::new()
|
||||
$CustomPermissions = [System.Collections.Generic.List[string]]::new()
|
||||
foreach ($PermType in $IncludePermissionType) {
|
||||
if ($PermType -in 'GpoApply', 'GpoEdit', 'GPOCustom', 'GpoEditDeleteModifySecurity', 'GPORead') {
|
||||
$IncludePermTypes.Add([Microsoft.GroupPolicy.GPPermissionType]::$PermType)
|
||||
} elseif ($PermType -in 'GpoOwner') {
|
||||
$IncludeOwner = $true
|
||||
} elseif ($PermType -in 'GpoRootCreate', 'GpoRootOwner') {
|
||||
$CustomPermissions.Add($PermType)
|
||||
}
|
||||
}
|
||||
foreach ($PermType in $ExcludePermissionType) {
|
||||
if ($PermType -in 'GpoApply', 'GpoEdit', 'GPOCustom', 'GpoEditDeleteModifySecurity', 'GPORead') {
|
||||
$ExcludePermTypes.Add([Microsoft.GroupPolicy.GPPermissionType]::$PermType)
|
||||
} elseif ($PermType -in 'GpoOwner') {
|
||||
$IncludeOwner = $false
|
||||
} elseif ($PermType -in 'GpoRootCreate', 'GpoRootOwner') {
|
||||
$CustomPermissions.Add($PermType)
|
||||
}
|
||||
}
|
||||
|
||||
$RootPermissions = Get-GPOZaurrPermissionRoot -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
$Permissions = Get-GPOZaurrPermission -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -IncludePermissionType $IncludePermTypes -ExcludePermissionType $ExcludePermissionType -Type $Type -PermitType $PermitType -IncludeOwner:$IncludeOwner
|
||||
$Entries = @(
|
||||
foreach ($Permission in $Permissions) {
|
||||
[PSCustomObject] @{
|
||||
PrincipalName = $Permission.PrincipalName
|
||||
PrincipalDomainName = $Permission.PrincipalDomainName
|
||||
Permission = $Permission.Permission
|
||||
PermissionType = $Permission.PermissionType
|
||||
PrincipalSid = $Permission.PrincipalSid
|
||||
PrincipalSidType = $Permission.PrincipalSidType
|
||||
PrincipalObjectClass = $Permission.PrincipalObjectClass
|
||||
DisplayName = $Permission.DisplayName
|
||||
DomainName = $Permission.DomainName
|
||||
}
|
||||
}
|
||||
foreach ($RootPermission in $RootPermissions) {
|
||||
[PSCustomObject] @{
|
||||
PrincipalName = $RootPermission.PrincipalName
|
||||
PrincipalDomainName = $RootPermission.PrincipalDomainName
|
||||
Permission = $RootPermission.Permission
|
||||
PermissionType = $RootPermission.PermissionType
|
||||
PrincipalSid = $RootPermission.PrincipalSid
|
||||
PrincipalSidType = $RootPermission.PrincipalSidType
|
||||
PrincipalObjectClass = $RootPermission.PrincipalObjectClass
|
||||
DisplayName = $RootPermission.GPONames
|
||||
DomainName = $RootPermission.DomainName
|
||||
}
|
||||
}
|
||||
)
|
||||
$PermissionsData = [ordered] @{}
|
||||
foreach ($Entry in $Entries) {
|
||||
$Key = -join ($Entry.Permission, $Entry.PrincipalName, $Entry.PrincipalDomainName)
|
||||
if (-not $PermissionsData[$Key]) {
|
||||
$PermissionsData[$Key] = [PSCustomObject] @{
|
||||
Permission = $Entry.Permission
|
||||
PrincipalName = $Entry.PrincipalName
|
||||
PrincipalDomainName = $Entry.PrincipalDomainName
|
||||
PrincipalSidType = $Entry.PrincipalSidType
|
||||
DomainName = $Entry.DomainName
|
||||
PermissionType = $Entry.PermissionType
|
||||
GPOCOunt = 0
|
||||
GPONames = [System.Collections.Generic.List[string]]::new()
|
||||
}
|
||||
}
|
||||
#if ($IncludeNames) {
|
||||
$PermissionsData[$Key].GPONames.Add($Entry.DisplayName)
|
||||
#}
|
||||
$PermissionsData[$Key].GPOCOunt = $PermissionsData[$Key].GPOCOunt + ($Entry.DisplayName).Count
|
||||
}
|
||||
$PermissionsData.Values
|
||||
|
||||
<#
|
||||
($Entries | Group-Object -Property Permission, PrincipalSidType, PrincipalName, PrincipalDomainName, DomainName, PermissionType) | ForEach-Object {
|
||||
$Property = $_.Name -split ', '
|
||||
Write-Verbose "$Property - $($Property.Count)"
|
||||
if ($Property[0] -eq 'GpoOwner') {
|
||||
[PSCustomObject] @{
|
||||
Permission = $Property[0]
|
||||
PrincipalSidType = $Property[1]
|
||||
PrincipalName = $Property[2]
|
||||
PrincipalDomainName = $Property[3]
|
||||
DomainName = $Property[4]
|
||||
PermissionType = 'Allow'
|
||||
GPOCount = $_.Count
|
||||
GPONames = if ($Separator) { $_.Group.DisplayName -join $Separator } else { $_.Group.DisplayName }
|
||||
}
|
||||
} elseif ($Property.Count -eq 5) {
|
||||
[PSCustomObject] @{
|
||||
Permission = $Property[0]
|
||||
PrincipalSidType = $Property[1]
|
||||
PrincipalName = $Property[2]
|
||||
PrincipalDomainName = $Property[3]
|
||||
DomainName = $Property[4]
|
||||
PermissionType = if ($Property[5]) { $Property[5] } else { 'Owner' }
|
||||
GPOCount = $_.Count
|
||||
GPONames = if ($Separator) { $_.Group.DisplayName -join $Separator } else { $_.Group.DisplayName }
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] @{
|
||||
Permission = $Property[0]
|
||||
PrincipalSidType = $Property[1]
|
||||
PrincipalName = ''
|
||||
PrincipalDomainName = ''
|
||||
DomainName = $Property[2]
|
||||
PermissionType = if ($Property[3]) { $Property[3] } else { 'Owner' }
|
||||
GPOCount = $_.Count
|
||||
GPONames = if ($Separator) { $_.Group.DisplayName -join $Separator } else { $_.Group.DisplayName }
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
function Get-GPOZaurrSysvol {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[string[]] $ExcludeDomainControllers,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
|
||||
[switch] $SkipRODC,
|
||||
[Array] $GPOs,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $VerifyDomainControllers
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeDomainControllers $ExcludeDomainControllers -IncludeDomainControllers $IncludeDomainControllers -SkipRODC:$SkipRODC -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
Write-Verbose "Get-WinADGPOSysvolFolders - Processing $Domain"
|
||||
$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
|
||||
Try {
|
||||
[Array]$GPOs = Get-GPO -All -Domain $Domain -Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrSysvol - Couldn't get GPOs from $Domain. Error: $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
if ($GPOs.Count -ge 2) {
|
||||
if (-not $VerifyDomainControllers) {
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Domain -Domain $Domain
|
||||
} else {
|
||||
foreach ($Server in $ForestInformation['DomainDomainControllers']["$Domain"]) {
|
||||
Write-Verbose "Get-GPOZaurrSysvol - Processing $Domain \ $($Server.HostName.Trim())"
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Server.Hostname -Domain $Domain
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurrSysvol - GPO count for $Domain is less then 2. This is not expected for fully functioning domain. Skipping processing SYSVOL folder."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
function Get-GPOZaurrSysvolDFSR {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[string[]] $ExcludeDomainControllers,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
|
||||
[switch] $SkipRODC,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[string] $SearchDFSR = 'SYSVOL Share'
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeDomainControllers $ExcludeDomainControllers -IncludeDomainControllers $IncludeDomainControllers -SkipRODC:$SkipRODC -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
Write-Verbose "Get-GPOZaurrSysvolDFSR - Processing $Domain"
|
||||
foreach ($DC in $ForestInformation.DomainDomainControllers[$Domain]) {
|
||||
Write-Verbose "Get-GPOZaurrSysvolDFSR - Processing $Domain \ $($DC.HostName)"
|
||||
#$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
|
||||
$DFSRConfig = Get-CimInstance -Namespace 'root\microsoftdfs' -Class 'dfsrreplicatedfolderconfig' -ComputerName $($DC.HostName) | Where-Object { $_.ReplicatedFolderName -eq $SearchDFSR }
|
||||
$DFSR = Get-CimInstance -Namespace 'root\microsoftdfs' -Class 'dfsrreplicatedfolderinfo' -ComputerName $($DC.HostName) | Where-Object { $_.ReplicatedFolderName -eq $SearchDFSR }
|
||||
if ($DFSR -and $DFSRConfig -and ($DFSR.ReplicatedFolderGuid -eq $DFSRConfig.ReplicatedFolderGuid)) {
|
||||
[PSCustomObject] @{
|
||||
ComputerName = $DFSR.PSComputerName
|
||||
DomainName = $Domain
|
||||
ConflictPath = $DFSRConfig.ConflictPath
|
||||
LastConflictCleanupTime = $DFSR.LastConflictCleanupTime
|
||||
CurrentConflictSizeInMb = $DFSR.CurrentConflictSizeInMb
|
||||
MaximumConflictSizeInMb = $DFSRConfig.ConflictSizeInMb
|
||||
LastErrorCode = $DFSR.LastErrorCode
|
||||
LastErrorMessageId = $DFSR.LastErrorMessageId
|
||||
LastTombstoneCleanupTime = $DFSR.LastTombstoneCleanupTime
|
||||
ReplicatedFolderGuid = $DFSR.ReplicatedFolderGuid
|
||||
DFSRConfig = $DFSRConfig
|
||||
DFSR = $DFSR
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurrSysvolDFSR - Couldn't process $($DC.HostName). Conditions not met."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-14
@@ -1,11 +1,4 @@
|
||||
function Get-WMIFilter {
|
||||
param(
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
function Get-GPOZaurrWMI {
|
||||
function Get-GPOZaurrWMI {
|
||||
[cmdletBinding()]
|
||||
Param(
|
||||
[Guid[]] $Guid,
|
||||
@@ -13,10 +6,11 @@ function Get-GPOZaurrWMI {
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $AsHashtable
|
||||
)
|
||||
$wmiFilterAttr = "msWMI-Name", "msWMI-Parm1", "msWMI-Parm2", "msWMI-Author", "msWMI-ID", 'CanonicalName', 'Created', 'Modified'
|
||||
|
||||
$Dictionary = [ordered] @{}
|
||||
$wmiFilterAttr = 'msWMI-Name', 'msWMI-Parm1', 'msWMI-Parm2', 'msWMI-Author', 'msWMI-ID', 'CanonicalName', 'Created', 'Modified'
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
@@ -41,7 +35,7 @@ function Get-GPOZaurrWMI {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$ldapFilter = "(objectClass=msWMI-Som)"
|
||||
$ldapFilter = '(objectClass=msWMI-Som)'
|
||||
Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)"
|
||||
@@ -59,14 +53,14 @@ function Get-GPOZaurrWMI {
|
||||
-join ($WMI[$i + 5], ';' , $WMI[$i + 6])
|
||||
}
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
$WMIObject = [PSCustomObject] @{
|
||||
DisplayName = $_.'msWMI-Name'
|
||||
Description = $_.'msWMI-Parm1'
|
||||
DomainName = $Domain
|
||||
#NameSpace = $WMI[$i + 5]
|
||||
#Query = $WMI[$i + 6]
|
||||
QueryCount = $Data.Count
|
||||
Query = $Data -join ","
|
||||
Query = $Data -join ','
|
||||
Author = $_.'msWMI-Author'
|
||||
ID = $_.'msWMI-ID'
|
||||
Created = $_.Created
|
||||
@@ -75,9 +69,17 @@ function Get-GPOZaurrWMI {
|
||||
CanonicalName = $_.CanonicalName
|
||||
DistinguishedName = $_.'DistinguishedName'
|
||||
}
|
||||
if (-not $AsHashtable) {
|
||||
$WMIObject
|
||||
} else {
|
||||
$Dictionary[$WMIObject.ID] = $WMIObject
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ($AsHashtable) {
|
||||
$Dictionary
|
||||
}
|
||||
}
|
||||
<#
|
||||
CanonicalName : ad.evotec.xyz/System/WMIPolicy/SOM/{E988C890-BDBC-4946-87B5-BF70F39F4686}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
function Get-GPOZaurrDictionary {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string] $Splitter = [System.Environment]::NewLine
|
||||
)
|
||||
foreach ($Policy in $Script:GPODitionary.Keys) {
|
||||
|
||||
if ($Script:GPODitionary[$Policy].ByReports) {
|
||||
[Array] $Type = foreach ($T in $Script:GPODitionary[$Policy].ByReports ) {
|
||||
$T.Report
|
||||
}
|
||||
|
||||
} else {
|
||||
[Array]$Type = foreach ($T in $Script:GPODitionary[$Policy].Types) {
|
||||
( -join ($T.Category, '/', $T.Settings))
|
||||
}
|
||||
}
|
||||
|
||||
[PSCustomObject] @{
|
||||
Name = $Policy
|
||||
Types = $Type -join $Splitter
|
||||
Path = $Script:GPODitionary[$Policy].GPOPath -join $Splitter
|
||||
#Details = $Script:GPODitionary[$Policy]
|
||||
}
|
||||
}
|
||||
}
|
||||
+145
-135
@@ -12,9 +12,6 @@
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[string[]] $Type,
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $NoTranslation,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
@@ -26,7 +23,7 @@
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[ValidateSet('HTML', 'Object', 'Excel')][string[]] $OutputType = 'Object',
|
||||
[ValidateSet('HTML', 'Object')][string[]] $OutputType = 'Object',
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
@@ -36,27 +33,34 @@
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $Open,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $Online,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $CategoriesOnly,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $SingleObject
|
||||
[switch] $SingleObject,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $SkipNormalize,
|
||||
|
||||
[Parameter(ParameterSetName = 'Default')]
|
||||
[Parameter(ParameterSetName = 'Local')]
|
||||
[switch] $SkipCleanup,
|
||||
|
||||
[switch] $Extended
|
||||
)
|
||||
if ($Type.Count -eq 0) {
|
||||
$Type = $Script:GPODitionary.Keys
|
||||
}
|
||||
if ($GPOPath) {
|
||||
Write-Verbose "Invoke-GPOZaurr - Reading GPOs from $GPOPath"
|
||||
if (Test-Path -LiteralPath $GPOPath) {
|
||||
<#
|
||||
$GPOListPath = [io.path]::Combine($GPOPath, "GPOList.xml")
|
||||
if ($GPOListPath) {
|
||||
$GPOs = Import-Clixml -Path $GPOListPath
|
||||
} else {
|
||||
|
||||
}
|
||||
#>
|
||||
$GPOFiles = Get-ChildItem -LiteralPath $GPOPath -Recurse -File -Filter *.xml
|
||||
[Array] $GPOs = foreach ($File in $GPOFiles) {
|
||||
if ($File.Name -ne 'GPOList.xml') {
|
||||
@@ -75,174 +79,180 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Find-GPO - $GPOPath doesn't exists."
|
||||
Write-Warning "Invoke-GPOZaurr - $GPOPath doesn't exists."
|
||||
return
|
||||
}
|
||||
} else {
|
||||
Write-Verbose "Invoke-GPOZaurr - Query AD for GPOs"
|
||||
[Array] $GPOs = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
# This caches single reports.
|
||||
$TemporaryCachedSingleReports = [ordered] @{}
|
||||
$TemporaryCachedSingleReports['ReportsSingle'] = [ordered] @{}
|
||||
# This will be returned
|
||||
$Output = [ordered] @{}
|
||||
$OutputByGPO = [ordered] @{}
|
||||
$TranslatedOutput = [ordered] @{}
|
||||
$CachedCategories = [ordered] @{}
|
||||
$Output['Reports'] = [ordered] @{}
|
||||
$Output['CategoriesFull'] = [ordered] @{}
|
||||
|
||||
Write-Verbose "Invoke-GPOZaurr - Loading GPO Report to Categories"
|
||||
[Array] $GPOCategories = foreach ($GPO in $GPOs) {
|
||||
if ($GPOPath) {
|
||||
$GPOOutput = $GPO.GPOOutput
|
||||
} else {
|
||||
[xml] $GPOOutput = Get-GPOReport -Guid $GPO.GUID -Domain $GPO.DomainName -ReportType Xml
|
||||
}
|
||||
Get-GPOCategories -GPO $GPO -GPOOutput $GPOOutput.GPO -Splitter $Splitter -FullObjects:$FullObjects -CachedCategories $CachedCategories
|
||||
Get-GPOCategories -GPO $GPO -GPOOutput $GPOOutput.GPO -Splitter $Splitter -FullObjects:$FullObjects -CachedCategories $Output['CategoriesFull']
|
||||
}
|
||||
|
||||
# Return Categories or save it
|
||||
$Output['Categories'] = $GPOCategories | Select-Object -Property * -ExcludeProperty DataSet
|
||||
if ($CategoriesOnly) {
|
||||
return $GPOCategories | Select-Object -Property * -ExcludeProperty DataSet
|
||||
} else {
|
||||
$Output['Categories'] = $GPOCategories | Select-Object -Property * -ExcludeProperty DataSet
|
||||
# Return Categories only
|
||||
return $Output['Categories']
|
||||
}
|
||||
# Save Cached Categories
|
||||
$Output['CategoriesFull'] = $CachedCategories
|
||||
# Process Reporting
|
||||
$Output['Reports'] = [ordered] @{}
|
||||
|
||||
if ($CachedCategories.Count -gt 0) {
|
||||
# We check our dictionary for reports that are based on reports to make sure we run CodeSingle separatly
|
||||
[Array] $FindRequiredSingle = foreach ($Key in $Script:GPODitionary.Keys) {
|
||||
$Script:GPODitionary[$Key].ByReports.Report
|
||||
}
|
||||
# Build reports based on categories
|
||||
if ($Output['CategoriesFull'].Count -gt 0) {
|
||||
foreach ($Report in $Type) {
|
||||
|
||||
Write-Verbose "Invoke-GPOZaurr - Processing report type $Report"
|
||||
foreach ($CategoryType in $Script:GPODitionary[$Report].Types) {
|
||||
|
||||
$Category = $CategoryType.Category
|
||||
$Settings = $CategoryType.Settings
|
||||
|
||||
# Those are checks for making sure we have data to be even able to process it
|
||||
if (-not $CachedCategories[$Category]) {
|
||||
if (-not $Output['CategoriesFull'][$Category]) {
|
||||
continue
|
||||
}
|
||||
if (-not $CachedCategories[$Category][$Settings]) {
|
||||
if (-not $Output['CategoriesFull'][$Category][$Settings]) {
|
||||
continue
|
||||
}
|
||||
# Translation
|
||||
$CategorizedGPO = $CachedCategories[$Category][$Settings]
|
||||
$CategorizedGPO = $Output['CategoriesFull'][$Category][$Settings]
|
||||
foreach ($GPO in $CategorizedGPO) {
|
||||
if (-not $Output['Reports'][$Report]) {
|
||||
$Output['Reports'][$Report] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
# Create temporary storage for "single gpo" reports
|
||||
# it's required if we want to base reports on other reports later on
|
||||
if (-not $TemporaryCachedSingleReports['ReportsSingle'][$Report]) {
|
||||
$TemporaryCachedSingleReports['ReportsSingle'][$Report] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
# Make sure translated gpo is null
|
||||
$TranslatedGpo = $null
|
||||
if ($SingleObject) {
|
||||
if ($SingleObject -or ($Report -in $FindRequiredSingle)) {
|
||||
# We either create 1 GPO with multiple settings to return it as user requested it
|
||||
# Or we process it only because we need to base it for reports based on other reports
|
||||
if (-not $Script:GPODitionary[$Report]['CodeSingle']) {
|
||||
# sometimes code and code single are identical. To not define things two times, one can just skip it
|
||||
If ($Script:GPODitionary[$Report]['Code']) {
|
||||
$Script:GPODitionary[$Report]['CodeSingle'] = $Script:GPODitionary[$Report]['Code']
|
||||
}
|
||||
}
|
||||
if ($Script:GPODitionary[$Report]['CodeSingle']) {
|
||||
#Write-Verbose "Invoke-GPOZaurr - Processing $Report single entry mode"
|
||||
$TranslatedGpo = Invoke-Command -ScriptBlock $Script:GPODitionary[$Report]['CodeSingle']
|
||||
}
|
||||
} else {
|
||||
if ($Script:GPODitionary[$Report]['Code']) {
|
||||
$TranslatedGpo = Invoke-Command -ScriptBlock $Script:GPODitionary[$Report]['Code']
|
||||
}
|
||||
}
|
||||
foreach ($T in $TranslatedGpo) {
|
||||
$Output['Reports'][$Report].Add($T)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $Output
|
||||
<#
|
||||
foreach ($GPO in $GPOs) {
|
||||
if ($GPOPath) {
|
||||
$GPOOutput = $GPO.GPOOutput
|
||||
} else {
|
||||
[xml] $GPOOutput = Get-GPOReport -Guid $GPO.GUID -Domain $GPO.DomainName -ReportType Xml
|
||||
}
|
||||
[Array] $Data = Get-XMLStandard -GPO $GPO -GPOOutput $GPOOutput.GPO -Splitter $Splitter -FullObjects:$FullObjects
|
||||
foreach ($D in $Data) {
|
||||
if (-not $Output["$($D.GpoCategory)"]) {
|
||||
$Output["$($D.GpoCategory)"] = [ordered] @{}
|
||||
}
|
||||
if (-not $Output["$($D.GpoCategory)"]["$($D.GpoSettings)"]) {
|
||||
$Output["$($D.GpoCategory)"]["$($D.GpoSettings)"] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$Output["$($D.GpoCategory)"]["$($D.GpoSettings)"].Add($D)
|
||||
|
||||
if (-not $OutputByGPO["$($D.DomainName)"]) {
|
||||
$OutputByGPO["$($D.DomainName)"] = [ordered] @{}
|
||||
}
|
||||
if (-not $OutputByGPO[$D.DomainName][$D.DisplayName]) {
|
||||
$OutputByGPO[$D.DomainName][$D.DisplayName] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$OutputByGPO[$D.DomainName][$D.DisplayName].Add($D)
|
||||
}
|
||||
|
||||
}
|
||||
if ($NoTranslation) {
|
||||
if ($OutputType -contains 'Object') {
|
||||
$Output
|
||||
}
|
||||
} else {
|
||||
foreach ($Report in $Type) {
|
||||
$Category = $Script:GPODitionary[$Report]['Category']
|
||||
$Settings = $Script:GPODitionary[$Report]['Settings']
|
||||
$TranslatedOutput[$Report] = Invoke-GPOTranslation -InputData $Output -Category $Category -Settings $Settings -Report $Report
|
||||
}
|
||||
if ($OutputType -contains 'Object') {
|
||||
$TranslatedOutput
|
||||
}
|
||||
}
|
||||
|
||||
if ($NoTranslation) {
|
||||
$SingleSource = $Output
|
||||
} else {
|
||||
$SingleSource = $TranslatedOutput
|
||||
}
|
||||
|
||||
if ($OutputPath) {
|
||||
$FolderPath = $OutputPath
|
||||
} else {
|
||||
$FolderPath = [io.path]::GetTempPath()
|
||||
}
|
||||
if ($OutputType -contains 'HTML') {
|
||||
$FilePathHTML = [io.path]::Combine($FolderPath, "GPOZaurr-Summary-$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss')).html")
|
||||
Write-Warning "Invoke-GPOZaurr - $FilePathHTML"
|
||||
New-HTML {
|
||||
foreach ($GPOCategory in $SingleSource.Keys) {
|
||||
New-HTMLTab -Name $GPOCategory {
|
||||
if ($SingleSource["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $SingleSource["$GPOCategory"].Keys) {
|
||||
New-HTMLTab -Name $GpoSettings {
|
||||
if ($SingleSource[$GPOCategory][$GpoSettings].Count -gt 0) {
|
||||
New-HTMLTable -DataTable $SingleSource[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
if ($Report -in $FindRequiredSingle) {
|
||||
foreach ($T in $TranslatedGpo) {
|
||||
$TemporaryCachedSingleReports['ReportsSingle'][$Report].Add($T)
|
||||
}
|
||||
}
|
||||
if ($SingleObject) {
|
||||
foreach ($T in $TranslatedGpo) {
|
||||
$Output['Reports'][$Report].Add($T)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($SingleSource[$GPOCategory].Count -gt 0) {
|
||||
New-HTMLTable -DataTable $SingleSource[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $GpoSettings
|
||||
}
|
||||
if (-not $SingleObject) {
|
||||
# We want each GPO to be listed multiple times if it makes sense for reporting
|
||||
# think drive mapping - showing 1 mapping of a drive per object even if there are 50 drive mappings within 1 gpo
|
||||
# this would result in 50 objects created
|
||||
if ($Script:GPODitionary[$Report]['Code']) {
|
||||
#Write-Verbose "Invoke-GPOZaurr - Processing $Report multi entry mode"
|
||||
$TranslatedGpo = Invoke-Command -ScriptBlock $Script:GPODitionary[$Report]['Code']
|
||||
foreach ($T in $TranslatedGpo) {
|
||||
$Output['Reports'][$Report].Add($T)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML:$Open.IsPresent -FilePath $FilePathHTML
|
||||
}
|
||||
}
|
||||
if ($OutputType -contains 'Excel') {
|
||||
$FilePathExcel = [io.path]::Combine($FolderPath, "GPOZaurr-Summary-$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss')).xlsx")
|
||||
Write-Warning "Invoke-GPOZaurr - $FilePathExcel"
|
||||
foreach ($GPOCategory in $SingleSource.Keys) {
|
||||
if ($SingleSource["$GPOCategory"] -is [System.Collections.IDictionary]) {
|
||||
foreach ($GpoSettings in $SingleSource["$GPOCategory"].Keys) {
|
||||
if ($SingleSource[$GPOCategory][$GpoSettings].Count -gt 0) {
|
||||
ConvertTo-Excel -DataTable $SingleSource[$GPOCategory][$GpoSettings] -AllProperties -ExcelWorkSheetName $GpoSettings -FilePath $FilePathExcel -AutoFilter -AutoFit -Option Rename
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($SingleSource[$GPOCategory].Count -gt 0) {
|
||||
ConvertTo-Excel -DataTable $SingleSource[$GPOCategory] -AllProperties -ExcelWorkSheetName $GPOCategory -FilePath $FilePathExcel -AutoFilter -AutoFit -Option Rename
|
||||
# Those reports are based on other reports (for example already processed registry settings)
|
||||
# This is useful where going thru registry collections may not be efficient enough to try and read it directly again
|
||||
foreach ($Report in $Type) {
|
||||
foreach ($ReportType in $Script:GPODitionary[$Report].ByReports) {
|
||||
if (-not $Output['Reports'][$Report]) {
|
||||
$Output['Reports'][$Report] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$FindReport = $ReportType.Report
|
||||
Write-Verbose "Invoke-GPOZaurr - Processing reports based on other report $Report ($FindReport)"
|
||||
foreach ($GPO in $TemporaryCachedSingleReports['ReportsSingle'][$FindReport]) {
|
||||
$TranslatedGpo = Invoke-Command -ScriptBlock $Script:GPODitionary[$Report]['CodeReport']
|
||||
foreach ($T in $TranslatedGpo) {
|
||||
$Output['Reports'][$Report].Add($T)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Open) {
|
||||
Invoke-Item -Path $FilePathExcel
|
||||
}
|
||||
# Normalize - meaning that before we return each GPO report we make sure that each entry has the same column names regardless which one is first.
|
||||
# Normally if you would have a GPO with just 2 entries for given subject (say LAPS), and then another GPO having 5 settings for the same type
|
||||
# and you would display them one after another - all entries would be shown using first object which has less properties then 2nd or 3rd object
|
||||
# to make sure all objects are having same (even empty) properties we "normalize" it
|
||||
if (-not $SkipNormalize) {
|
||||
foreach ($Report in [string[]] $Output['Reports'].Keys) {
|
||||
$FirstProperties = 'DisplayName', 'DomainName', 'GUID', 'GpoType'
|
||||
#$EndProperties = 'CreatedTime', 'ModifiedTime', 'ReadTime', 'Filters', 'Linked', 'LinksCount', 'Links'
|
||||
$EndProperties = 'Filters', 'Linked', 'LinksCount', 'Links'
|
||||
$Properties = $Output['Reports'][$Report] | Select-Properties -ExcludeProperty ($FirstProperties + $EndProperties) -AllProperties -WarningAction SilentlyContinue
|
||||
$DisplayProperties = @(
|
||||
$FirstProperties
|
||||
foreach ($Property in $Properties) {
|
||||
$Property
|
||||
}
|
||||
$EndProperties
|
||||
)
|
||||
$Output['Reports'][$Report] = $Output['Reports'][$Report] | Select-Object -Property $DisplayProperties
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
$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-GPOZaurr - Cleaning up output"
|
||||
Remove-EmptyValue -Hashtable $Output -Recursive
|
||||
}
|
||||
if ($Extended) {
|
||||
$Output
|
||||
} else {
|
||||
if ($Output.Reports) {
|
||||
if ($OutputType -eq 'Object') {
|
||||
$Output.Reports
|
||||
}
|
||||
if ($OutputType -eq 'HTML') {
|
||||
if (-not $OutputPath) {
|
||||
$OutputPath = Get-FileName -Extension 'html' -Temporary
|
||||
Write-Warning "Invoke-GPOZaurr - OutputPath not given. Using $OutputPath"
|
||||
}
|
||||
Write-Verbose "Invoke-GPOZaurr - Generating HTML output"
|
||||
New-HTML {
|
||||
New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
|
||||
New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey
|
||||
New-HTMLTableOption -DataStore JavaScript
|
||||
foreach ($Key in $Output.Reports.Keys) {
|
||||
New-HTMLTab -Name $Key {
|
||||
Write-Verbose "Invoke-GPOZaurr - Generating HTML Table for $Key"
|
||||
New-HTMLTable -DataTable $Output.Reports[$Key] -Filtering -Title $Key
|
||||
}
|
||||
}
|
||||
} -FilePath $OutputPath -ShowHTML:$Open -Online:$Online
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Invoke-GPOZaurr - There was no data output for requested types."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[scriptblock] $SourcesAutoCompleter = {
|
||||
@@ -250,4 +260,4 @@
|
||||
|
||||
$Script:GPODitionary.Keys | Sort-Object | Where-Object { $_ -like "*$wordToComplete*" }
|
||||
}
|
||||
Register-ArgumentCompleter -CommandName Find-GPO -ParameterName Type -ScriptBlock $SourcesAutoCompleter
|
||||
Register-ArgumentCompleter -CommandName Invoke-GPOZaurr -ParameterName Type -ScriptBlock $SourcesAutoCompleter
|
||||
@@ -0,0 +1,204 @@
|
||||
function Invoke-GPOZaurrSupport {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('NativeHTML', 'HTML', 'XML', 'Object')][string] $Type = 'HTML',
|
||||
[alias('Server')][string] $ComputerName,
|
||||
[alias('User')][string] $UserName,
|
||||
[string] $Path,
|
||||
[string] $Splitter = [System.Environment]::NewLine,
|
||||
[switch] $PreventShow,
|
||||
[switch] $Offline,
|
||||
[switch] $ForceGPResult
|
||||
)
|
||||
# if user didn't choose anything, lets run as currently logged in user locally
|
||||
if (-not $UserName -and -not $ComputerName) {
|
||||
$UserName = $Env:USERNAME
|
||||
# we can also check if the session is Administrative and if so request computer policies
|
||||
if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
$ComputerName = $Env:COMPUTERNAME
|
||||
}
|
||||
}
|
||||
If ($Type -eq 'HTML') {
|
||||
$Exists = Get-Command -Name 'New-HTML' -ErrorAction SilentlyContinue
|
||||
if (-not $Exists) {
|
||||
Write-Warning "Invoke-GPOZaurrSupport - PSWriteHTML module is required for HTML functionality. Use XML, Object or NativeHTML option instead."
|
||||
return
|
||||
}
|
||||
}
|
||||
$Command = Get-Command -Name 'Get-GPResultantSetOfPolicy' -ErrorAction SilentlyContinue
|
||||
$NativeCommand = Get-Command -Name 'gpresult' -ErrorAction SilentlyContinue
|
||||
if (-not $Command -and -not $NativeCommand) {
|
||||
Write-Warning "Invoke-GPOZaurrSupport - Neither gpresult or Get-GPResultantSetOfPolicy are available. Terminating."
|
||||
return
|
||||
}
|
||||
|
||||
$SplatPolicy = @{}
|
||||
if ($Type -in 'Object', 'XML', 'HTML') {
|
||||
if ($Path) {
|
||||
$SplatPolicy['Path'] = $Path
|
||||
} else {
|
||||
$SplatPolicy['Path'] = [io.path]::GetTempFileName().Replace('.tmp', ".xml")
|
||||
}
|
||||
$SplatPolicy['ReportType'] = 'xml'
|
||||
} elseif ($Type -eq 'NativeHTML') {
|
||||
if ($Path) {
|
||||
$SplatPolicy['Path'] = $Path
|
||||
} else {
|
||||
$SplatPolicy['Path'] = [io.path]::GetTempFileName().Replace('.tmp', ".html")
|
||||
}
|
||||
$SplatPolicy['ReportType'] = 'html'
|
||||
}
|
||||
if ($ComputerName) {
|
||||
$SplatPolicy['Computer'] = $ComputerName
|
||||
}
|
||||
if ($UserName) {
|
||||
$SplatPolicy['User'] = $UserName
|
||||
}
|
||||
if ($Command -and -not $ForceGPResult) {
|
||||
try {
|
||||
#Write-Verbose "Request-GPOZaurr - ComputerName: $($SplatPolicy['Computer']) UserName: $($SplatPolicy['User'])"
|
||||
$ResultantSetPolicy = Get-GPResultantSetOfPolicy @SplatPolicy -ErrorAction Stop
|
||||
} catch {
|
||||
if ($_.Exception.Message -eq 'Exception from HRESULT: 0x80041003') {
|
||||
Write-Warning "Request-GPOZaurr - Are you running as admin? $($_.Exception.Message)"
|
||||
return
|
||||
} else {
|
||||
$ErrorMessage = $($_.Exception.Message).Replace([Environment]::NewLine, ' ')
|
||||
Write-Warning "Request-GPOZaurr - Error: $ErrorMessage"
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$Arguments = @(
|
||||
if ($SplatPolicy['Computer']) {
|
||||
"/S $ComputerName"
|
||||
}
|
||||
if ($SplatPolicy['User']) {
|
||||
"/USER $($SplatPolicy['User'])"
|
||||
}
|
||||
if ($SplatPolicy['ReportType'] -eq 'HTML') {
|
||||
'/H'
|
||||
} elseif ($SplatPolicy['ReportType'] -eq 'XML') {
|
||||
'/X'
|
||||
}
|
||||
$SplatPolicy['Path']
|
||||
"/F"
|
||||
)
|
||||
Write-Verbose "Invoke-GPOZaurrSupport - GPResult Arguments: $Arguments"
|
||||
Start-Process -NoNewWindow -FilePath 'gpresult' -ArgumentList $Arguments -Wait
|
||||
}
|
||||
if ($Type -eq 'NativeHTML') {
|
||||
if (-not $PreventShow) {
|
||||
Write-Verbose "Invoke-GPOZaurrSupport - Opening up file $($SplatPolicy['Path'])"
|
||||
Start-Process -FilePath $SplatPolicy['Path']
|
||||
}
|
||||
return
|
||||
}
|
||||
# Loads created XML by resultant Output
|
||||
if ($SplatPolicy.Path -and (Test-Path -LiteralPath $SplatPolicy.Path)) {
|
||||
[xml] $PolicyContent = Get-Content -LiteralPath $SplatPolicy.Path
|
||||
if ($PolicyContent) {
|
||||
# lets remove temporary XML file
|
||||
Remove-Item -LiteralPath $SplatPolicy.Path
|
||||
} else {
|
||||
Write-Warning "Request-GPOZaurr - Couldn't load XML file from drive $($SplatPolicy.Path). Terminating."
|
||||
return
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Request-GPOZaurr - Couldn't find XML file on drive $($SplatPolicy.Path). Terminating."
|
||||
return
|
||||
}
|
||||
if ($ComputerName) {
|
||||
if (-not $PolicyContent.Rsop.'ComputerResults'.EventsDetails) {
|
||||
Write-Warning "Request-GPOZaurr - Windows Events for Group Policy are missing. Amount of data will be limited. Firewall issue?"
|
||||
}
|
||||
}
|
||||
if ($Type -eq 'XML') {
|
||||
$PolicyContent.Rsop
|
||||
} else {
|
||||
$Output = [ordered] @{
|
||||
ResultantSetPolicy = $ResultantSetPolicy
|
||||
}
|
||||
if ($PolicyContent.Rsop.ComputerResults) {
|
||||
$Output.ComputerResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultantSetPolicy $ResultantSetPolicy -ResultsType 'ComputerResults' -Splitter $Splitter
|
||||
}
|
||||
if ($PolicyContent.Rsop.UserResults) {
|
||||
$Output.UserResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultantSetPolicy $ResultantSetPolicy -ResultsType 'UserResults' -Splitter $Splitter
|
||||
}
|
||||
|
||||
New-GPOZaurrReportConsole -Results $Output
|
||||
if ($Type -contains 'Object') {
|
||||
$Output
|
||||
} elseif ($Type -contains 'HTML') {
|
||||
New-GPOZaurrReportHTML -Path $Path -Offline:$Offline -Open:(-not $PreventShow) -Support $Output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
|
||||
|
||||
GPRESULT [/S system [/U username [/P [password]]]] [/SCOPE scope]
|
||||
[/USER targetusername] [/R | /V | /Z] [(/X | /H) <filename> [/F]]
|
||||
|
||||
Description:
|
||||
This command line tool displays the Resultant Set of Policy (RSoP)
|
||||
information for a target user and computer.
|
||||
|
||||
Parameter List:
|
||||
/S system Specifies the remote system to connect to.
|
||||
|
||||
/U [domain\]user Specifies the user context under which the
|
||||
command should run.
|
||||
Can not be used with /X, /H.
|
||||
|
||||
/P [password] Specifies the password for the given user
|
||||
context. Prompts for input if omitted.
|
||||
Cannot be used with /X, /H.
|
||||
|
||||
/SCOPE scope Specifies whether the user or the
|
||||
computer settings need to be displayed.
|
||||
Valid values: "USER", "COMPUTER".
|
||||
|
||||
/USER [domain\]user Specifies the user name for which the
|
||||
RSoP data is to be displayed.
|
||||
|
||||
/X <filename> Saves the report in XML format at the
|
||||
location and with the file name specified
|
||||
by the <filename> parameter. (valid in Windows
|
||||
Vista SP1 and later and Windows Server 2008 and later)
|
||||
|
||||
/H <filename> Saves the report in HTML format at the
|
||||
location and with the file name specified by
|
||||
the <filename> parameter. (valid in Windows
|
||||
at least Vista SP1 and at least Windows Server 2008)
|
||||
|
||||
/F Forces Gpresult to overwrite the file name
|
||||
specified in the /X or /H command.
|
||||
|
||||
/R Displays RSoP summary data.
|
||||
|
||||
/V Specifies that verbose information should
|
||||
be displayed. Verbose information provides
|
||||
additional detailed settings that have
|
||||
been applied with a precedence of 1.
|
||||
|
||||
/Z Specifies that the super-verbose
|
||||
information should be displayed. Super-
|
||||
verbose information provides additional
|
||||
detailed settings that have been applied
|
||||
with a precedence of 1 and higher. This
|
||||
allows you to see if a setting was set in
|
||||
multiple places. See the Group Policy
|
||||
online help topic for more information.
|
||||
|
||||
/? Displays this help message.
|
||||
|
||||
|
||||
Examples:
|
||||
GPRESULT /R
|
||||
GPRESULT /H GPReport.html
|
||||
GPRESULT /USER targetusername /V
|
||||
GPRESULT /S system /USER targetusername /SCOPE COMPUTER /Z
|
||||
GPRESULT /S system /U username /P password /SCOPE USER /V
|
||||
#>
|
||||
@@ -0,0 +1,75 @@
|
||||
function Remove-GPOZaurrBroken {
|
||||
[alias('Remove-GPOZaurrOrphaned')]
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[ValidateSet('SYSVOL', 'AD')][string[]] $Type = @('SYSVOL', 'AD'),
|
||||
[string] $BackupPath,
|
||||
[switch] $BackupDated,
|
||||
[int] $LimitProcessing = [int32]::MaxValue,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
if ($BackupPath) {
|
||||
if ($BackupDated) {
|
||||
$BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))"
|
||||
} else {
|
||||
$BackupFinalPath = $BackupPath
|
||||
}
|
||||
} else {
|
||||
$BackupFinalPath = ''
|
||||
}
|
||||
Get-GPOZaurrSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
|
||||
if ($Type -contains 'SYSVOL') {
|
||||
if ($_.Status -eq 'Not available in AD') {
|
||||
$_
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'AD') {
|
||||
if ($_.Status -eq 'Not available on SYSVOL') {
|
||||
$_
|
||||
}
|
||||
}
|
||||
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
if ($_.Status -eq 'Not available in AD') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Processing $($_.Path)"
|
||||
if ($BackupFinalPath) {
|
||||
Try {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Backing up $($_.Path)"
|
||||
Copy-Item -LiteralPath $_.Path -Recurse -Destination $BackupFinalPath -ErrorAction Stop
|
||||
$BackupWorked = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error backing up error: $($_.Exception.Message)"
|
||||
$BackupWorked = $false
|
||||
}
|
||||
}
|
||||
if ($BackupWorked -or $BackupFinalPath -eq '') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Deleting $($_.Path)"
|
||||
try {
|
||||
Remove-Item -Recurse -Force -LiteralPath $_.Path
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove file $($_.Path): $($_.Exception.Message)."
|
||||
}
|
||||
}
|
||||
} elseif ($_.Status -eq 'Not available on SYSVOL') {
|
||||
try {
|
||||
$ExistingObject = Get-ADObject -Identity $_.DistinguishedName -Server $_.DomainName -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error getting $($_.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
$ExistingObject = $null
|
||||
}
|
||||
if ($ExistingObject -and $ExistingObject.ObjectClass -eq 'groupPolicyContainer') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Removing DN: $($_.DistinguishedName) / ObjectClass: $($ExistingObject.ObjectClass)"
|
||||
try {
|
||||
Remove-ADObject -Server $_.DomainName -Identity $_.DistinguishedName -Recursive -Confirm:$false
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove $($_.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Remove-GPOZaurrBroken - DistinguishedName $($_.DistinguishedName) not found or ObjectClass is not groupPolicyContainer ($($ExistingObject.ObjectClass))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
function Remove-GPOZaurrEmptyFolders {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[ValidateSet('Adm')][string] $Folders,
|
||||
[int] $LimitProcessing = [int32]::MaxValue,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
Get-GPOZaurrEmptyFolders -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
|
||||
foreach ($Folder in $Folders) {
|
||||
if ($_.IsEmptyFolder -eq $true -and $_.Name -eq $Folder) {
|
||||
$_
|
||||
}
|
||||
}
|
||||
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurrEmptyFolders - Removing $($_.FullName)"
|
||||
Remove-Item -Path $_.FullName
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrEmptyFolders - Failed to remove directory $($_.FullName): $($_.Exception.Message)."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
function Remove-GPOZaurrFolders {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[string] $BackupPath,
|
||||
[switch] $BackupDated,
|
||||
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
|
||||
[Parameter(Mandatory)][ValidateSet('NTFRS', 'Empty')][string] $FolderType,
|
||||
[string[]] $FolderName,
|
||||
[int] $LimitProcessing = [int32]::MaxValue,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
if ($BackupPath) {
|
||||
if ($BackupDated) {
|
||||
$BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))"
|
||||
} else {
|
||||
$BackupFinalPath = $BackupPath
|
||||
}
|
||||
} else {
|
||||
$BackupFinalPath = ''
|
||||
}
|
||||
|
||||
Get-GPOZaurrFolders -Type $Type -FolderType $FolderType -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
|
||||
if ($FolderName) {
|
||||
foreach ($Folder in $FolderName) {
|
||||
if ($_.Name -eq $Folder) {
|
||||
$_
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
if ($BackupFinalPath) {
|
||||
$SYSVOLRoot = "\\$($_.DomainName)\SYSVOL\$($_.DomainName)\"
|
||||
$DestinationFile = ($_.FullName).Replace($SYSVOLRoot, '')
|
||||
#$DestinationMissingFolder = $DestinationFile.Replace($DestinationFile, '')
|
||||
$DestinationFilePath = [system.io.path]::Combine($BackupFinalPath, $DestinationFile)
|
||||
#$DestinationFolderPath = [system.io.path]::Combine($BackupFinalPath, $DestinationMissingFolder)
|
||||
|
||||
Write-Verbose "Remove-GPOZaurrFolders - Backing up $($_.FullName)"
|
||||
Try {
|
||||
Copy-Item -LiteralPath $_.FullName -Recurse -Destination $DestinationFilePath -ErrorAction Stop -Force
|
||||
$BackupWorked = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrFolders - Error backing up error: $($_.Exception.Message)"
|
||||
$BackupWorked = $false
|
||||
}
|
||||
|
||||
}
|
||||
if ($BackupWorked -or $BackupFinalPath -eq '') {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurrFolders - Removing $($_.FullName)"
|
||||
Remove-Item -Path $_.FullName -Force -Recurse
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrFolders - Failed to remove directory $($_.FullName): $($_.Exception.Message)."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
function Remove-GPOZaurrOrphanedSysvolFolders {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[string] $BackupPath,
|
||||
[switch] $BackupDated,
|
||||
[int] $LimitProcessing = [int32]::MaxValue,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
if ($BackupPath) {
|
||||
if ($BackupDated) {
|
||||
$BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))"
|
||||
} else {
|
||||
$BackupFinalPath = $BackupPath
|
||||
}
|
||||
} else {
|
||||
$BackupFinalPath = ''
|
||||
}
|
||||
Get-GPOZaurrSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
|
||||
if ($_.Status -eq 'Orphaned GPO') {
|
||||
$_
|
||||
}
|
||||
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
Write-Verbose "Remove-GPOZaurrOrphanedSysvolFolders - Processing $($_.Path)"
|
||||
if ($BackupFinalPath) {
|
||||
Try {
|
||||
Write-Verbose "Remove-GPOZaurrOrphanedSysvolFolders - Backing up $($_.Path)"
|
||||
Copy-Item -LiteralPath $_.Path -Recurse -Destination $BackupFinalPath -ErrorAction Stop
|
||||
$BackupWorked = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrOrphanedSysvolFolders - Error backing up error: $($_.Exception.Message)"
|
||||
$BackupWorked = $false
|
||||
}
|
||||
}
|
||||
if ($BackupWorked -or $BackupFinalPath -eq '') {
|
||||
Write-Verbose "Remove-GPOZaurrOrphanedSysvolFolders - Deleting $($_.Path)"
|
||||
try {
|
||||
Remove-Item -Recurse -Force -LiteralPath $_.Path
|
||||
} catch {
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
Write-Warning "Remove-GPOZaurrOrphanedSysvolFolders - Failed to remove file $($_.Path): $($ErrorMessage)."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
[alias('GUID', 'GPOID')][string] $GPOGuid,
|
||||
|
||||
[string[]] $Principal,
|
||||
[validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
[validateset('DistinguishedName', 'Name', 'NetbiosName', 'Sid')][string] $PrincipalType = 'Sid',
|
||||
|
||||
[validateset('Unknown', 'NotAdministrative', 'Default')][string[]] $Type = 'Default',
|
||||
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
}
|
||||
}
|
||||
$null = New-Item -ItemType Directory -Path $GPOPath -Force
|
||||
Write-Verbose "Save-GPOZaurrFiles - Gathering GPO data"
|
||||
$Count = 0
|
||||
$GPOs = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($GPO in $GPOS) {
|
||||
$Count++
|
||||
Write-Verbose "Save-GPOZaurrFiles - Processing GPO ($Count/$($GPOS.Count)) $($GPO.DomainName) | $($GPO.DisplayName)"
|
||||
$XMLContent = Get-GPOReport -ID $GPO.Guid -ReportType XML -Domain $GPO.DomainName
|
||||
$GPODOmainFolder = [io.path]::Combine($GPOPath, $GPO.DomainName)
|
||||
if (-not (Test-Path -Path $GPODOmainFolder)) {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
function Select-GPOTranslation {
|
||||
[cmdletbInding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipeline)][System.Collections.IDictionary] $InputObject,
|
||||
[string] $Category,
|
||||
[string] $Settings
|
||||
)
|
||||
|
||||
$Important = [ordered] @{}
|
||||
$AllProperties = Select-Properties -AllProperties -Objects $InputObject.$Category.$Settings
|
||||
$MissingProperties = $AllProperties | Where-Object { $_ -notin 'DisplayName', 'DomainName', 'GUID', 'Linked', 'LinksCount', 'Links', 'GPOType', 'GPOCategory', 'GPOSettings' }
|
||||
$Types = foreach ($Property in $MissingProperties) {
|
||||
($InputObject.$Category.$Settings | Where-Object { $null -ne $_.$Property }).$Property | ForEach-Object {
|
||||
($_ | Get-Member -MemberType Properties) | Where-Object { $_.Name -notin 'Length' }
|
||||
}
|
||||
}
|
||||
$Important['AllProperties'] = $AllProperties
|
||||
$Important['MissingProperties'] = $MissingProperties
|
||||
$Important['Types'] = $Types | Select-Object -Unique
|
||||
$Important['Data'] = $InputObject.$Category.$Settings
|
||||
$Important
|
||||
}
|
||||
@@ -0,0 +1,457 @@
|
||||
function Show-GPOZaurr {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string] $FilePath,
|
||||
[ValidateSet(
|
||||
'GPOList', 'GPOOrphans', 'GPOPermissions', 'GPOPermissionsRoot', 'GPOFiles',
|
||||
'GPOConsistency', 'GPOOwners', 'GPOAnalysis', 'NetLogon'
|
||||
)][string[]] $Type
|
||||
)
|
||||
$Script:Reporting = [ordered] @{
|
||||
|
||||
}
|
||||
# Provide version check for easy use
|
||||
$GPOZaurrVersion = Get-Command -Name 'Show-GPOZaurr' -ErrorAction SilentlyContinue
|
||||
|
||||
[Array] $GitHubReleases = (Get-GitHubLatestRelease -Url "https://api.github.com/repos/evotecit/GpoZaurr/releases" -Verbose:$false)
|
||||
|
||||
$LatestVersion = $GitHubReleases[0]
|
||||
if (-not $LatestVersion.Errors) {
|
||||
if ($GPOZaurrVersion.Version -eq $LatestVersion.Version) {
|
||||
$Script:Reporting['Version'] = "GPOZaurr Current/Latest: $($LatestVersion.Version) at $($LatestVersion.PublishDate)"
|
||||
} elseif ($GPOZaurrVersion.Version -lt $LatestVersion.Version) {
|
||||
$Script:Reporting['Version'] = "GPOZaurr Current: $($GPOZaurrVersion.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Update?"
|
||||
} elseif ($GPOZaurrVersion.Version -gt $LatestVersion.Version) {
|
||||
$Script:Reporting['Version'] = "GPOZaurr Current: $($GPOZaurrVersion.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Lucky you!"
|
||||
}
|
||||
} else {
|
||||
$Script:Reporting['Version'] = "GPOZaurr Current: $($GPOZaurrVersion.Version)"
|
||||
}
|
||||
|
||||
# Gather data
|
||||
$TimeLog = Start-TimeLog
|
||||
if ($Type -contains 'GPOList' -or $null -eq $Type) {
|
||||
$TimeLogGPOList = Start-TimeLog
|
||||
Write-Verbose -Message "Show-GPOZaurr - Processing GPO List"
|
||||
$GPOSummary = Get-GPOZaurr
|
||||
$GPOLinkedStatus = $GPOSummary.Where( { $_.Linked -eq $true }, 'split')
|
||||
[Array] $GPONotLinked = $GPOLinkedStatus[1]
|
||||
[Array] $GPOLinked = $GPOLinkedStatus[0]
|
||||
$GPOEmptyStatus = $GPOSummary.Where( { $_.Empty -eq $true }, 'split' )
|
||||
[Array] $GPOEmpty = $GPOEmptyStatus[0]
|
||||
[Array] $GPONotEmpty = $GPOEmptyStatus[1]
|
||||
$GPOTotal = $GPOSummary.Count
|
||||
$TimeEndGPOList = Stop-TimeLog -Time $TimeLog -Option OneLiner
|
||||
}
|
||||
if ($Type -contains 'GPOOrphans' -or $null -eq $Type) {
|
||||
#Write-Color -Text "[Info] ", "Processing GPOOrphans" -Color Yellow, White
|
||||
Write-Verbose -Message "Show-GPOZaurr - Processing GPO Sysvol"
|
||||
$GPOOrphans = Get-GPOZaurrBroken
|
||||
|
||||
$NotAvailableInAD = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
$NotAvailableOnSysvol = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
$NotAvailablePermissionIssue = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
foreach ($_ in $GPOOrphans) {
|
||||
if ($_.Status -eq 'Not available in AD') {
|
||||
$NotAvailableInAD.Add($NotAvailableInAD)
|
||||
} elseif ($_.Status -eq 'Not available on SYSVOL') {
|
||||
$NotAvailableOnSysvol.Add($NotAvailableInAD)
|
||||
} elseif ( $_.Status -eq 'Permissions issue') {
|
||||
$NotAvailablePermissionIssue.Add($NotAvailableInAD)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOPermissions' -or $null -eq $Type) {
|
||||
#Write-Color -Text "[Info] ", "Processing GPOPermissions" -Color Yellow, White
|
||||
Write-Verbose -Message "Show-GPOZaurr - Processing GPO Permissions"
|
||||
$GPOPermissions = Get-GPOZaurrPermission -Type All -IncludePermissionType GpoEditDeleteModifySecurity, GpoEdit, GpoCustom -IncludeOwner
|
||||
}
|
||||
if ($Type -contains 'GPOConsistency' -or $null -eq $Type) {
|
||||
Write-Verbose -Message "Show-GPOZaurr - Processing GPO Permissions Consistency"
|
||||
$GPOPermissionsConsistency = Get-GPOZaurrPermissionConsistency -Type All -VerifyInheritance
|
||||
[Array] $Inconsistent = $GPOPermissionsConsistency.Where( { $_.ACLConsistent -eq $true } , 'split' )
|
||||
[Array] $InconsistentInside = $GPOPermissionsConsistency.Where( { $_.ACLConsistentInside -eq $true }, 'split' )
|
||||
}
|
||||
if ($Type -contains 'GPOPermissionsRoot' -or $null -eq $Type) {
|
||||
Write-Verbose -Message "Show-GPOZaurr - Processing GPO Permissions Root"
|
||||
$GPOPermissionsRoot = Get-GPOZaurrPermissionRoot
|
||||
}
|
||||
if ($Type -contains 'GPOOwners' -or $null -eq $Type) {
|
||||
Write-Verbose "Show-GPOZaurr - Processing GPO Owners"
|
||||
$GPOOwners = Get-GPOZaurrOwner -IncludeSysvol
|
||||
$IsOwnerConsistent = $GPOOwners.Where( { $_.IsOwnerConsistent -eq $true } , 'split' )
|
||||
$IsOwnerAdministrative = $GPOOwners.Where( { $_.IsOwnerAdministrative -eq $true } , 'split' )
|
||||
}
|
||||
if ($Type -contains 'NetLogon' -or $null -eq $Type) {
|
||||
Write-Verbose "Get-GPOZaurrNetLogon - Processing NETLOGON Share"
|
||||
$Netlogon = Get-GPOZaurrNetLogon
|
||||
}
|
||||
if ($Type -contains 'GPOAnalysis' -or $null -eq $Type) {
|
||||
Write-Verbose "Show-GPOZaurr - Processing GPO Analysis"
|
||||
$GPOContent = Invoke-GPOZaurr
|
||||
}
|
||||
if ($Type -contains 'GPOFiles') {
|
||||
Write-Verbose "Show-GPOZaurr - Processing GPOFiles"
|
||||
$GPOFiles = Get-GPOZaurrFiles
|
||||
}
|
||||
$TimeEnd = Stop-TimeLog -Time $TimeLog -Option OneLiner
|
||||
|
||||
# Generate pretty HTML
|
||||
Write-Verbose "Show-GPOZaurr - Generating HTML"
|
||||
New-HTML {
|
||||
New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey
|
||||
New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
|
||||
New-HTMLPanelStyle -BorderRadius 0px
|
||||
New-HTMLTableOption -DataStore JavaScript -BoolAsString
|
||||
|
||||
New-HTMLHeader {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLSection {
|
||||
New-HTMLText -Text "Report generated on $(Get-Date)" -Color Blue
|
||||
} -JustifyContent flex-start -Invisible
|
||||
New-HTMLSection {
|
||||
New-HTMLText -Text $Script:Reporting['Version'] -Color Blue
|
||||
} -JustifyContent flex-end -Invisible
|
||||
}
|
||||
}
|
||||
|
||||
New-HTMLTab -Name 'Overview' {
|
||||
if ($Type -contains 'GPOConsistency' -or $Type -contains 'GPOList' -or $null -eq $Type) {
|
||||
New-HTMLSection -Invisible {
|
||||
if ($Type -contains 'GPOList' -or $null -eq $Type) {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents ', 'Linked / Empty and Unlinked Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies total: ', $GPOTotal -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies linked: ', $GPOLinked.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $GPONotLinked.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $GPOEmpty.Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Usually empty or unlinked Group Policies are safe to delete.'
|
||||
New-HTMLChart -Title 'Group Policies Summary' {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
#New-ChartLegend -Names 'Unlinked', 'Linked', 'Empty', 'Total' -Color Salmon, PaleGreen, PaleVioletRed, PaleTurquoise
|
||||
New-ChartLegend -Names 'Bad', 'Good' -Color PaleGreen, Salmon
|
||||
#New-ChartBar -Name 'Group Policies' -Value $GPONotLinked.Count, $GPOLinked.Count, $GPOEmpty.Count, $GPOTotal
|
||||
New-ChartBar -Name 'Linked' -Value $GPOLinked.Count, $GPONotLinked.Count
|
||||
New-ChartBar -Name 'Empty' -Value $GPONotEmpty.Count, $GPOEmpty.Count
|
||||
} -TitleAlignment center
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOConsistency' -or $null -eq $Type) {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents ', 'permissions consistency between Active Directory and SYSVOL for Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Top level permissions consistency: ', $Inconsistent[0].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Inherited permissions consistency: ', $InconsistentInside[0].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Inconsistent top level permissions: ', $Inconsistent[1].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Inconsistent inherited permissions: ", $InconsistentInside[1].Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Having incosistent permissions on AD in comparison to those on SYSVOL can lead to uncontrolled ability to modify them.'
|
||||
New-HTMLChart {
|
||||
New-ChartLegend -Names 'Bad', 'Good' -Color PaleGreen, Salmon
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Consistent', 'Inconsistent'
|
||||
New-ChartBar -Name 'TopLevel' -Value $Inconsistent[0].Count, $Inconsistent[1].Count
|
||||
New-ChartBar -Name 'Inherited' -Value $InconsistentInside[0].Count, $InconsistentInside[1].Count
|
||||
} -Title 'Permissions Consistency' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOOwners' -or $Type -contains 'GPOOrphans' -or $null -eq $Type) {
|
||||
New-HTMLSection -Invisible {
|
||||
if ($Type -contains 'GPOOwners' -or $null -eq $Type) {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents Group Policy owners and whether they are administrative and consistent. By design an owner of Group Policy should be Domain Admins or Enterprise Admins group only to prevent malicious takeover. ', `
|
||||
"It's also important that owner in Active Directory matches owner on SYSVOL (file system)."
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color PaleGreen, Orchid
|
||||
New-ChartBar -Name 'Is administrative' -Value $IsOwnerAdministrative[0].Count, $IsOwnerAdministrative[1].Count
|
||||
New-ChartBar -Name 'Is consistent' -Value $IsOwnerConsistent[0].Count, $IsOwnerConsistent[1].Count
|
||||
} -Title 'Group Policy Owners'
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOOrphans' -or $null -eq $Type) {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents ', 'Broken / Orphaned Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $NotAvailableInAD.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $NotAvailableOnSysvol.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $NotAvailablePermissionIssue.Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Those problems must be resolved before doing other clenaup activities.'
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'Permissions Issue' -Color Crimson, LightCoral, IndianRed
|
||||
New-ChartBar -Name 'Orphans' -Value $NotAvailableInAD.Count, $NotAvailableOnSysvol.Count, $NotAvailablePermissionIssue.Count
|
||||
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOList' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Group Policies Summary' {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following table shows a list of group policies. ', 'By using following table you can easily find which GPOs can be safely deleted because those are empty or unlinked.' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies total: ', $GPOTotal -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies linked: ', $GPOLinked.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $GPONotLinked.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $GPOEmpty.Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policies List' {
|
||||
New-HTMLTable -DataTable $GPOSummary -Filtering {
|
||||
New-HTMLTableCondition -Name 'Empty' -Value $true -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Linked' -Value $false -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Empty & Unlinked Group Policies' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to remove empty or unlinked group policies'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep {
|
||||
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOOrphans' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Health State' {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -TextBlock {
|
||||
"Following table shows list of all group policies and their status in AD and SYSVOL. Due to different reasons it's "
|
||||
"possible that "
|
||||
} -FontSize 10pt
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $NotAvailableInAD.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $NotAvailableOnSysvol.Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $NotAvailablePermissionIssue.Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "Follow the steps below table to get Active Directory Group Policies in healthy state." -FontSize 10pt
|
||||
}
|
||||
New-HTMLSection -Name 'Health State of Group Policies' {
|
||||
New-HTMLTable -DataTable $GPOOrphans -Filtering {
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Not available in AD" -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Not available on SYSVOL" -BackgroundColor LightCoral -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Permissions issue" -BackgroundColor MediumVioletRed -ComparisonType string -Color White
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix GPOs which are not available on SYSVOL or AD.'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Show-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOOrphans
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrBroken
|
||||
$GPOOutput | Format-Table
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix GPOs not available on SYSVOL' {
|
||||
New-HTMLText -Text "Following command when executed runs cleanup procedure that removes all broken GPOs on SYSVOL side."
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type SYSVOL -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X broken GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix GPOs not available on AD' {
|
||||
New-HTMLText -Text "Following command when executed runs cleanup procedure that removes all broken GPOs on Active Directory side."
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type AD -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type AD -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X broken GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted on AD side, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Show-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOOrphans
|
||||
}
|
||||
New-HTMLText -Text "If everything is health in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'NetLogon' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'NetLogon' {
|
||||
New-HTMLTable -DataTable $Netlogon -Filtering
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOPermissionsRoot' -or $Type -contains 'GPOOwners' -or
|
||||
$Type -contains 'GPOPermissions' -or $Type -contains 'GPOConsistency' -or
|
||||
$null -eq $Type
|
||||
) {
|
||||
New-HTMLTab -Name 'Permissions' {
|
||||
if ($Type -contains 'GPOPermissionsRoot' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Root' {
|
||||
New-HTMLTable -DataTable $GPOPermissionsRoot -Filtering
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOOwners' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Owners' {
|
||||
New-HTMLTable -DataTable $GPOOwners -Filtering
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOPermissions' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Edit & Modify' {
|
||||
New-HTMLTable -DataTable $GPOPermissions -Filtering
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOConsistency' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Permissions Consistency' {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following table presents ', 'permissions consistency between Active Directory and SYSVOL for Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Top level permissions consistency: ', $Inconsistent[0].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Inherited permissions consistency: ', $InconsistentInside[0].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Inconsistent top level permissions: ', $Inconsistent[1].Count -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Inconsistent inherited permissions: ", $InconsistentInside[1].Count -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Having incosistent permissions on AD in comparison to those on SYSVOL can lead to uncontrolled ability to modify them. Please notice that if ', `
|
||||
' Not available ', 'is visible in the table you should first fix related, more pressing issue, before fixing permissions inconsistency.' -FontWeight normal, bold, normal
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Permissions Consistency' {
|
||||
New-HTMLTable -DataTable $GPOPermissionsConsistency -Filtering {
|
||||
New-HTMLTableCondition -Name 'ACLConsistent' -Value $false -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value $false -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistent' -Value $true -BackgroundColor PaleGreen -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value $true -BackgroundColor PaleGreen -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistent' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Permissions Consistency' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix permissions consistency'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing permissions inconsistencies. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Show-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentBefore.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrPermissionConsistency
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent permissions' {
|
||||
New-HTMLText -Text "Following command when executed fixes inconsistent permissions."
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
New-HTMLText -Text "Make sure to fill in TargetDomain to match your Domain Admin permission account"
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -IncludeDomains "TargetDomain" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -LimitProcessing 2 -IncludeDomains "TargetDomain"
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed repairs only first X inconsistent permissions. Use LimitProcessing parameter to prevent mass fixing and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be fixed, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent downlevel permissions' {
|
||||
New-HTMLText -Text "Unfortunetly this step is manual until automation is developed. "
|
||||
New-HTMLText -Text "If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Show-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentAfter.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
New-HTMLText -Text "If everything is health in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'GPOAnalysis' -or $null -eq $Type) {
|
||||
New-HTMLTab -Name 'Analysis' {
|
||||
foreach ($Key in $GPOContent.Keys) {
|
||||
New-HTMLTab -Name $Key {
|
||||
New-HTMLTable -DataTable $GPOContent[$Key] -Filtering -Title $Key
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML -FilePath $FilePath
|
||||
}
|
||||
@@ -21,6 +21,16 @@
|
||||
|
||||
## To install
|
||||
|
||||
GPOZaurr requires `RSAT` installed to provide results. If you don't have them you can install them as below. Keep in mind it also installs GUI tools so it shouldn't be installed on user workstations.
|
||||
|
||||
```powershell
|
||||
# Windows 10 Latest
|
||||
Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
|
||||
Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
|
||||
```
|
||||
|
||||
Finally just install module:
|
||||
|
||||
```powershell
|
||||
Install-Module -Name GPOZaurr -AllowClobber -Force
|
||||
```
|
||||
@@ -39,10 +49,68 @@ That's it. Whenever there's a new version, you run the command, and you can enjo
|
||||
|
||||
## Changelog
|
||||
|
||||
- 0.0.66 - 22.10.2020
|
||||
- Improved `Show-GPOZaurr` (WIP)
|
||||
- 0.0.65 - 22.10.2020
|
||||
- Improved `Show-GPOZaurr` (WIP)
|
||||
- 0.0.64 - 21.10.2020
|
||||
- Renamed `Remove-GPOZaurrOrphaned` to `Remove-GPOZaurrBroken` keeping it as an alias
|
||||
- Renamed `Get-GPOZaurrSysvol` to `Get-GPOZaurrBroken` keeping it as an alias
|
||||
- Improved `Show-GPOZaurr` (WIP)
|
||||
- 0.0.63 - 19.10.2020
|
||||
- Renamed `Invoke-GPOZaurrContent` back to `Invoke-GPOZaurr`
|
||||
- Added `Show-GPOZaurr` (WIP)
|
||||
- Added `OutputType`,`OutputType`,`Open`,`Online` parameters to `Invoke-GPOZaurr`
|
||||
- Added `Get-GPOZaurrNetLogon`
|
||||
- Improved `Get-GPOZaurrOwner`
|
||||
- Fixes `Get-GPOZaurrSysvol`
|
||||
- 0.0.62 - 14.10.2020
|
||||
- Renamed `Invoke-GPOZaurr` to `Invoke-GPOZaurrContent` - I want to use `Invoke-GPOZaurr` for something else
|
||||
- Improvements to `Get-GPOZaurrPermissionConsistency` for GPOs without SYSVOL to be reported properly
|
||||
- Added `Get-GPOZaurrPermissionRoot`
|
||||
- Renamed `Remove-GPOZaurrOrphanedSysvolFolders` to `Remove-GPOZaurrOrphaned`
|
||||
- Improved `Remove-GPOZaurrOrphaned` to deal with orphaned folders but also orphaned AD GPO (No sysvol data)
|
||||
- Improved `Get-GPOZaurrSysVol` to detect orphaned SYSVOL or AD GPO objects
|
||||
- Improved `Get-GPOZaurrSysVol` to detect permissions issue when reading AD GPO objects
|
||||
- Added `Get-GPOZaurrPermissionRoot` to show which users/groups have control over all GPOs (allowed to create/modify)
|
||||
- Improved `Get-GPOZaurrPermissionSummary` to include `Get-GPOZaurrPermissionRoot` custom permissions
|
||||
- Updated `Remove-GPOZaurrPermission`
|
||||
- Updated `Get-GpoZaurrPermission`
|
||||
- Updated `Get-GPOZaurrFiles` to better handle access issue
|
||||
- Reversed parameters `Get-GPOZaurrFiles` from `Limited` to `ExtendedMetaData` and fixed missing columns
|
||||
- 0.0.61 - 31.08.2020
|
||||
- Improvement to `Get-GPOZaurrPermissionSummary`
|
||||
- Fixes to `ConvertFrom-CSExtension`
|
||||
- Fixes to `Find-CSExtension`
|
||||
- 0.0.59 - 26.08.2020
|
||||
- Improvement to `Get-GPOZaurrPermissionSummary`
|
||||
- 0.0.58 - 26.08.2020
|
||||
- Improvement to `Get-GPOZaurrPermissionSummary`
|
||||
- 0.0.57 - 26.08.2020
|
||||
- Improvement to `Get-GPOZaurrPermissionSummary`
|
||||
- 0.0.56 - 26.08.2020
|
||||
- Added `Get-GPOZaurrPermissionSummary`
|
||||
- 0.0.55 - 17.08.2020
|
||||
- Improved `Get-GPOZaurrInheritance`
|
||||
- 0.0.54 - 16.08.2020
|
||||
- Added `Invoke-GPOZaurrSupport` (WIP)
|
||||
- Added `ConvertFrom-CSExtension`
|
||||
- Added `Find-CSExtension`
|
||||
- Added `Get-GPOZaurrInheritance`
|
||||
- 0.0.53 - 16.08.2020
|
||||
- Bad release
|
||||
- 0.0.52 - 16.08.2020
|
||||
- Bad release
|
||||
- 0.0.51 - 2.08.2020
|
||||
- Updates to `Invoke-GPOZaurr` - still work in progress
|
||||
- Added `Get-GPOZaurrSysvolDFSR`
|
||||
- Added `Clear-GPOZaurrSysvolDFSR` (requires testing)
|
||||
- 0.0.50 - 29.07.2020
|
||||
- Updates to couple of commands
|
||||
- 0.0.49 - 23.07.2020
|
||||
- Hidden files were skipped - and people do crazy things with them
|
||||
- 0.0.48 - 21.07.2020
|
||||
- Added `Get-GPOZaurrFilesPolicyDefinitions`
|
||||
- Added `Get-GPOZaurrFilesPolicyDefinition`
|
||||
- Updates to `Invoke-GPOZaurr` - still work in progress
|
||||
- Updates to `Get-GPOZaurrFiles` - still work in progress
|
||||
- Updates to `Remove-GPOZaurrOrphanedSysvolFolders` with backup and support for domains
|
||||
|
||||
Reference in New Issue
Block a user