From e76c4d90941633e2f263444fbf6e88d6987e8325 Mon Sep 17 00:00:00 2001 From: Przemyslaw Klys Date: Sun, 28 Jun 2020 15:47:37 +0200 Subject: [PATCH] Update --- ...mple-29-FindGPO-FromDisk-Notranslation.ps1 | 22 ++++ ...sk.ps1 => Example-29-FindGPO-FromDisk.ps1} | 4 +- Examples/Example-29-FindGPO-NoTranslation.ps1 | 19 +++ Examples/Example-29-FindGPO.ps1 | 10 +- Private/Find-MissingProperties.ps1 | 15 +++ Private/GpoTypes/RegistrySettings.ps1 | 76 ++++++++++++ .../GpoTypes/RegistrySettingsCollection.ps1 | 33 ++++++ Private/Invoke-GPOTranslation.ps1 | 109 +++++++++++++----- Private/Script.GPODictionary.ps1 | 4 +- 9 files changed, 258 insertions(+), 34 deletions(-) create mode 100644 Examples/Example-29-FindGPO-FromDisk-Notranslation.ps1 rename Examples/{Example-29-FindGPOfromDisk.ps1 => Example-29-FindGPO-FromDisk.ps1} (94%) create mode 100644 Examples/Example-29-FindGPO-NoTranslation.ps1 create mode 100644 Private/Find-MissingProperties.ps1 create mode 100644 Private/GpoTypes/RegistrySettings.ps1 create mode 100644 Private/GpoTypes/RegistrySettingsCollection.ps1 diff --git a/Examples/Example-29-FindGPO-FromDisk-Notranslation.ps1 b/Examples/Example-29-FindGPO-FromDisk-Notranslation.ps1 new file mode 100644 index 0000000..523826c --- /dev/null +++ b/Examples/Example-29-FindGPO-FromDisk-Notranslation.ps1 @@ -0,0 +1,22 @@ +Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force + +# Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport + +$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 ($Output["$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 $Key + } + } + } else { + New-HTMLTable -DataTable $OutputNoTranslation[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $Key + } + } + } +} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-NoTranslationFromDisk.html \ No newline at end of file diff --git a/Examples/Example-29-FindGPOfromDisk.ps1 b/Examples/Example-29-FindGPO-FromDisk.ps1 similarity index 94% rename from Examples/Example-29-FindGPOfromDisk.ps1 rename to Examples/Example-29-FindGPO-FromDisk.ps1 index f4135f9..c80d263 100644 --- a/Examples/Example-29-FindGPOfromDisk.ps1 +++ b/Examples/Example-29-FindGPO-FromDisk.ps1 @@ -2,7 +2,7 @@ # Use Save-GPOZaurrFiles -GPOPath $ENV:USERPROFILE\Desktop\GPOExport -$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' #-NoTranslation +$Output = Invoke-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\GPOExportTest' $Output | Format-Table * New-HTML { @@ -19,4 +19,4 @@ New-HTML { } } } -} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO.html \ No newline at end of file +} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-FromDisk.html \ No newline at end of file diff --git a/Examples/Example-29-FindGPO-NoTranslation.ps1 b/Examples/Example-29-FindGPO-NoTranslation.ps1 new file mode 100644 index 0000000..3d465a5 --- /dev/null +++ b/Examples/Example-29-FindGPO-NoTranslation.ps1 @@ -0,0 +1,19 @@ +Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force + +$Output = Invoke-GPOZaurr -NoTranslation + +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 $Key + } + } + } else { + New-HTMLTable -DataTable $Output[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $Key + } + } + } +} -Online -ShowHTML -FilePath $Env:UserProfile\Desktop\OutputFromFindGPO-NoTranslation.html \ No newline at end of file diff --git a/Examples/Example-29-FindGPO.ps1 b/Examples/Example-29-FindGPO.ps1 index ba4a344..fe11500 100644 --- a/Examples/Example-29-FindGPO.ps1 +++ b/Examples/Example-29-FindGPO.ps1 @@ -5,10 +5,14 @@ $Output = Invoke-GPOZaurr #-NoTranslation New-HTML { foreach ($GPOCategory in $Output.Keys) { New-HTMLTab -Name $GPOCategory { - foreach ($GpoSettings in $Output.$GPOCategory.Keys) { - New-HTMLTab -Name $GpoSettings { - New-HTMLTable -DataTable $Output[$GPOCategory][$GpoSettings] -ScrollX -DisablePaging -AllProperties -Title $Key + 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 $Key + } } + } else { + New-HTMLTable -DataTable $Output[$GPOCategory] -ScrollX -DisablePaging -AllProperties -Title $Key } } } diff --git a/Private/Find-MissingProperties.ps1 b/Private/Find-MissingProperties.ps1 new file mode 100644 index 0000000..49f02a8 --- /dev/null +++ b/Private/Find-MissingProperties.ps1 @@ -0,0 +1,15 @@ +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 +} \ No newline at end of file diff --git a/Private/GpoTypes/RegistrySettings.ps1 b/Private/GpoTypes/RegistrySettings.ps1 new file mode 100644 index 0000000..e50a2a1 --- /dev/null +++ b/Private/GpoTypes/RegistrySettings.ps1 @@ -0,0 +1,76 @@ +$RegistrySettings = [ordered] @{ + Category = 'RegistrySettings' + Settings = 'RegistrySettings' + # This is to make sure we're not loosing anything + # We will detect this and if something is missing provide details + PossibleProperties = @( + 'clsid', 'Registry', 'Collection' + ) + LoopOver = [ordered] @{ + Registry = @{ + 'Hive' = 'Properties', 'Hive' + 'Key' = 'Properties', 'Key' + 'Name' = 'Properties', 'Name' + 'Type' = 'Properties', 'Type' + 'action' = 'Properties', 'action' + 'displayDecimal' = 'Properties', 'displayDecimal' + 'default' = 'Properties', 'default' + 'Value' = 'Properties', 'Value' + 'Changed' = 'Changed' + 'GPOSettingOrder' = 'GPOSettingOrder' + 'Filters' = 'Filters' + } + } + Translate = [ordered] @{ + + } + Types = [ordered] @{ + 'Changed' = { try { [datetime]::Parse($args) } catch { $null } } + } +} + + + +function Set-SpecialObject { + [cmdletbInding()] + param( + $GPOEntry, + $DataDictionaryLoop, + $DataDictionary, + $DataObject, + $Key = 'Translate' + ) + $CreateGPO = [ordered]@{ + DisplayName = $GPOEntry.DisplayName #: WO_SEC_NTLM_Auth_Level + DomainName = $GPOEntry.DomainName #: area1.local + GUID = $GPOEntry.GUID #: 364B095E-C7BF-4CC1-9BFA-393BD38975E5 + GpoType = $GPOEntry.GpoType #: Computer + GpoCategory = $GPOEntry.GpoCategory #: SecuritySettings + GpoSettings = $GPOEntry.GpoSettings #: SecurityOptions + } + foreach ($PropertyName in $DataDictionaryLoop.Keys) { + # We get property that we expect on our $GPOEntry object + $Property = $DataDictionaryLoop[$Key][$PropertyName] + + # Since it's possible we may be interested in something that is a nested property we need to do some looping into the object + $Value = $DataObject + foreach ($P in $Property) { + $Value = $Value.$P + } + # Now we simply assing that value to new GPO Entry + # But before we do so, we need to check if it has required type + if ($DataDictionary[$Report]['Types'][$PropertyName]) { + # This basically checks in dictionary if we want to convert the type from a string to lets say boolean or something else + $CreateGPO["$PropertyName"] = Invoke-Command -Command $DataDictionary[$Report]['Types'][$PropertyName] -ArgumentList $Value + } else { + $CreateGPO["$PropertyName"] = $Value + } + } + + # return GPO Entry + $CreateGPO['Linked'] = $GPOEntry.Linked #: True + $CreateGPO['LinksCount'] = $GPOEntry.LinksCount #: 1 + $CreateGPO['Links'] = $GPOEntry.Links #: area1.local + [PSCustomObject] $CreateGPO + +} \ No newline at end of file diff --git a/Private/GpoTypes/RegistrySettingsCollection.ps1 b/Private/GpoTypes/RegistrySettingsCollection.ps1 new file mode 100644 index 0000000..0fa87a0 --- /dev/null +++ b/Private/GpoTypes/RegistrySettingsCollection.ps1 @@ -0,0 +1,33 @@ +$RegistrySettingsCollection = [ordered] @{ + Category = 'RegistrySettings' + Settings = 'RegistrySettings' + # This is to make sure we're not loosing anything + # We will detect this and if something is missing provide details + PossibleProperties = @( + 'clsid', 'Registry', 'Collection' + ) + LoopOver = [ordered] @{ + Collection = [ordered] @{ + 'Changed' = 'Changed' + 'GPOSettingOrder' = 'GPOSettingOrder' + 'Filters' = 'Filters' + 'BypassErrors' = 'bypassErrors' + Registry = [ordered] @{ + 'Hive' = 'Properties', 'Hive' + 'Key' = 'Properties', 'Key' + 'Name' = 'Properties', 'Name' + 'Type' = 'Properties', 'Type' + 'action' = 'Properties', 'action' + 'displayDecimal' = 'Properties', 'displayDecimal' + 'default' = 'Properties', 'default' + 'Value' = 'Properties', 'Value' + } + } + } + Translate = [ordered] @{ + + } + Types = [ordered] @{ + 'Changed' = { try { [datetime]::Parse($args) } catch { $null } } + } +} \ No newline at end of file diff --git a/Private/Invoke-GPOTranslation.ps1 b/Private/Invoke-GPOTranslation.ps1 index 379ba70..2d78614 100644 --- a/Private/Invoke-GPOTranslation.ps1 +++ b/Private/Invoke-GPOTranslation.ps1 @@ -13,6 +13,7 @@ } # This section basically makes sure we check for all properties in GPO Types. # It's possible given small input of GPOs that I work with that this is not all... and needs updates + <# $AllProperties = Select-Properties -AllProperties -Objects $InputData.$Category.$Settings $MissingProperties = $AllProperties | Where-Object { $_ -notin 'DisplayName', 'DomainName', 'GUID', 'Linked', 'LinksCount', 'Links', 'GPOType', 'GPOCategory', 'GPOSettings' } [Array] $ConsiderAdding = foreach ($Property in $MissingProperties) { @@ -20,6 +21,8 @@ $Property } } + #> + $ConsiderAdding = Find-MissingProperties -Objects $InputData.$Category.$Settings -PossibleProperties $Script:GPODitionary[$Report]['PossibleProperties'] if ($ConsiderAdding.Count -gt 0) { Write-Warning "Invoke-Translation - We're missing property for $Category / $Settings - ($($ConsiderAdding -join ','))" } @@ -27,38 +30,88 @@ # Dictionary will need a lot of work and engine some improvements foreach ($GPOEntry in $InputData.$Category.$Settings) { # Create new GPO Entry with minimal required properties - $CreateGPO = [ordered]@{ - DisplayName = $GPOEntry.DisplayName #: WO_SEC_NTLM_Auth_Level - DomainName = $GPOEntry.DomainName #: area1.local - GUID = $GPOEntry.GUID #: 364B095E-C7BF-4CC1-9BFA-393BD38975E5 - GpoType = $GPOEntry.GpoType #: Computer - GpoCategory = $GPOEntry.GpoCategory #: SecuritySettings - GpoSettings = $GPOEntry.GpoSettings #: SecurityOptions - } + if ($Script:GPODitionary[$Report]['LoopOver'].Keys) { + foreach ($Key in $Script:GPODitionary[$Report]['LoopOver'].Keys) { + foreach ($DataObject in $GPOEntry.$Key) { + #Set-SpecialObject -GPOEntry $GPOEntry -DataDictionaryLoop $Script:GPODitionary[$Report]['LoopOver'][$Key] -DataDictionary $Script:GPODitionary[$Report] -DataObject $DataObject -Key $Key - # Lets loop thru each Translate Property - foreach ($PropertyName in $Script:GPODitionary[$Report]['Translate'].Keys) { - # We get property that we expect on our $GPOEntry object - $Property = $Script:GPODitionary[$Report]['Translate'][$PropertyName] + #$Script:GPODitionary[$Report]['LoopOver'][$Key].GetEnumerator() | Where-Object { $_.Value -is [System.Collections.IDictionary] } - # Since it's possible we may be interested in something that is a nested property we need to do some looping into the object - $Value = $GPOEntry - foreach ($P in $Property) { - $Value = $Value.$P + $CreateGPO = [ordered]@{ + DisplayName = $GPOEntry.DisplayName #: WO_SEC_NTLM_Auth_Level + DomainName = $GPOEntry.DomainName #: area1.local + GUID = $GPOEntry.GUID #: 364B095E-C7BF-4CC1-9BFA-393BD38975E5 + GpoType = $GPOEntry.GpoType #: Computer + GpoCategory = $GPOEntry.GpoCategory #: SecuritySettings + GpoSettings = $GPOEntry.GpoSettings #: SecurityOptions + } + + + + foreach ($PropertyName in $Script:GPODitionary[$Report]['LoopOver'][$Key].Keys) { + # We get property that we expect on our $GPOEntry object + $Property = $Script:GPODitionary[$Report]['LoopOver'][$Key][$PropertyName] + + # Since it's possible we may be interested in something that is a nested property we need to do some looping into the object + $Value = $DataObject + foreach ($P in $Property) { + $Value = $Value.$P + } + # Now we simply assing that value to new GPO Entry + # But before we do so, we need to check if it has required type + if ($Script:GPODitionary[$Report]['Types'][$PropertyName]) { + # This basically checks in dictionary if we want to convert the type from a string to lets say boolean or something else + $CreateGPO["$PropertyName"] = Invoke-Command -Command $Script:GPODitionary[$Report]['Types'][$PropertyName] -ArgumentList $Value + } else { + $CreateGPO["$PropertyName"] = $Value + } + } + + # return GPO Entry + $CreateGPO['Linked'] = $GPOEntry.Linked #: True + $CreateGPO['LinksCount'] = $GPOEntry.LinksCount #: 1 + $CreateGPO['Links'] = $GPOEntry.Links #: area1.local + [PSCustomObject] $CreateGPO + + + } } - # Now we simply assing that value to new GPO Entry - # But before we do so, we need to check if it has required type - if ($Script:GPODitionary[$Report]['Types'][$PropertyName]) { - # This basically checks in dictionary if we want to convert the type from a string to lets say boolean or something else - $CreateGPO["$PropertyName"] = Invoke-Command -Command $Script:GPODitionary[$Report]['Types'][$PropertyName] -ArgumentList $Value - } else { - $CreateGPO["$PropertyName"] = $Value + + } else { + #Set-SpecialObject -GPOEntry $GPOEntry -DataDictionaryLoop $Script:GPODitionary[$Report]['Translate'] -DataDictionary $Script:GPODitionary[$Report] -DataObject $GPOEntry + $CreateGPO = [ordered]@{ + DisplayName = $GPOEntry.DisplayName #: WO_SEC_NTLM_Auth_Level + DomainName = $GPOEntry.DomainName #: area1.local + GUID = $GPOEntry.GUID #: 364B095E-C7BF-4CC1-9BFA-393BD38975E5 + GpoType = $GPOEntry.GpoType #: Computer + GpoCategory = $GPOEntry.GpoCategory #: SecuritySettings + GpoSettings = $GPOEntry.GpoSettings #: SecurityOptions } + + # Lets loop thru each Translate Property + foreach ($PropertyName in $Script:GPODitionary[$Report]['Translate'].Keys) { + # We get property that we expect on our $GPOEntry object + $Property = $Script:GPODitionary[$Report]['Translate'][$PropertyName] + + # Since it's possible we may be interested in something that is a nested property we need to do some looping into the object + $Value = $GPOEntry + foreach ($P in $Property) { + $Value = $Value.$P + } + # Now we simply assing that value to new GPO Entry + # But before we do so, we need to check if it has required type + if ($Script:GPODitionary[$Report]['Types'][$PropertyName]) { + # This basically checks in dictionary if we want to convert the type from a string to lets say boolean or something else + $CreateGPO["$PropertyName"] = Invoke-Command -Command $Script:GPODitionary[$Report]['Types'][$PropertyName] -ArgumentList $Value + } else { + $CreateGPO["$PropertyName"] = $Value + } + } + # return GPO Entry + $CreateGPO['Linked'] = $GPOEntry.Linked #: True + $CreateGPO['LinksCount'] = $GPOEntry.LinksCount #: 1 + $CreateGPO['Links'] = $GPOEntry.Links #: area1.local + [PSCustomObject] $CreateGPO } - # return GPO Entry - $CreateGPO['Linked'] = $GPOEntry.Linked #: True - $CreateGPO['LinksCount'] = $GPOEntry.LinksCount #: 1 - $CreateGPO['Links'] = $GPOEntry.Links #: area1.local - [PSCustomObject] $CreateGPO } } \ No newline at end of file diff --git a/Private/Script.GPODictionary.ps1 b/Private/Script.GPODictionary.ps1 index 484a1fb..9d46f04 100644 --- a/Private/Script.GPODictionary.ps1 +++ b/Private/Script.GPODictionary.ps1 @@ -1,5 +1,7 @@ $Script:GPODitionary = @{ - SecurityOptions = $SecurityOptions + SecurityOptions = $SecurityOptions + RegistrySettings = $RegistrySettings + RegistrySettingsCollection = $RegistrySettingsCollection #LugsSettings = @{ # LocalUsersAndGroups = $LugsSettingsLocalUsersAndGroups