ExtensionData in GPO xml file
While parsing a GPO XML file, you‘ll eventually run into something like this
<Extension xmlns:q1="http://www.microsoft.com/GroupPolicy/Settings/Security" xsi:type="q1:SecuritySettings">
followed by a whole pile more of "q1:" like this:
<q1:SecurityOptions>
how to parse?
[xml]$xml
=
Get-GPOReport
-Name "Srvr-SecurityBaseLine"
-ReportType xml
$namespaceManager
=
New-Object
System.Xml.XmlNamespaceManager($xml.NameTable)
$namespaceManager.AddNamespace("q1",
"http://www.microsoft.com/GroupPolicy/Settings/Security")
$xpath
=
"//q1:SecurityOptions"
$securityOptions
=
$xml.SelectNodes($xpath,
$namespaceManager)
foreach ($securityOption
in
$securityOptions) {
Write-Host
"Found
'$($securityOption.Display.Name)'"
-ForegroundColor Blue
}
Get-GPO
-Guid 18f45a2d-317b-4669-84f7-02afacd3fe40 |
fl
Get-GPO
PCs-2023
|
fl
There are no more properties besides what this command gets.
That is, there is no -Properties
available.
gpresult /r – see also rsop
command results in text output, supposedly more complete than rsop. But rsop easier to navigate GUI pop-up. Not only that, but it indicates which policy affects each setting.
If you omit /scope
parameter for gpresult
, it supposedly
will display RSoP data for both the user and the computer. But in practice,
I’ve never seen it return anything for the computer. If I specify
/scope computer
, usually returns ERROR: Access Denied.
group policy editor (local) - see local group policy editor
Below may only apply to OU linis. I got it from here
$GPOPrecedence = (Get-ADOrganizationalUnit -filter * | Get-GPInheritance).GpoLinks | Select -Property Target,DisplayName,Enabled,Enforced,Order
gpmc.msc
sometimes when I run this, I get:
The permissions for this GPO in the SYSVOL folder are inconsistent with those in Active Directory. It is recommended that these permissions be consistent. To change the SYSVOL permissions to those in Active Directory, click OK.
I pretty much always click OK.
see also local group policy editor
$AllGroupPolicies
=
Get-GPO
-All
$AllGroupPolicies.Count
$AllGroupPolicies
|
ogv
You can save a specific Group Policy as an XML file. Let’s put it in My Documents directory
$path
=
[environment]::getfolderpath("mydocuments")
Get-GPOReport
-Name
"Srvr-2016"
-ReportType xml
-Path
"$path\Srvr-2016.xml"
and then read it back into an XML variable
[xml]$xml1 = Get-Content -Path "$($path)\Srvr-2016.xml"
But faster to just read directly into an XML variable
[xml]$xml = Get-GPOReport -Name "Srvr-2016" -ReportType xml
Here's an example that reads in registry stuff & put into CSV
$result
=
@()
foreach
($item
in
$xml.DocumentElement.Computer.ExtensionData.extension.RegistrySettings.ChildNodes) {
$result
+=
New-Object
-TypeName PSObject
-Property
@{
"name"
=
$item.Name
#"clsid" = $item.clsid
#"status" = $item.status
"image"
=
$item.image
#"changed" = $item.changed
#"uid" = $item.uid
"GPOSettingOrder"
=
$item.GPOSettingOrder
"propertyName"
=
$item.properties.name
"propertyAction"
=
$item.properties.action
"propertyDisplayDecimal"
=
$item.properties.displayDecimal
"propertyDefault"
=
$item.properties.default
#"propertyHive" = $item.properties.hive
"propertyKey"
=
$item.properties.key
"propertyType"
=
$item.properties.type
"propertyValue"
=
$item.properties.value
#"propertyValues" = $item.properties.Values
#"Filters" =$item.Filters
}
}
$result
=
$result
|
select name,
image,
GPOSettingOrder,
propertyName,
propertyAction,
propertyDisplayDecimal,
propertyDefault,
propertyKey,
propertyType,
propertyValue
$result
|
ogv
$result
|
Export-Csv
-Path
"$([environment]::getfolderpath("mydocuments"))\Registry1$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"
-Encoding UTF8
-NoTypeInformation
This example gets adds a namespace to be able to process
“q1
” XML elements to get security settings
$namespaceManager
=
New-Object
System.Xml.XmlNamespaceManager($xml.NameTable)
$namespaceManager.AddNamespace("q1",
"http://www.microsoft.com/GroupPolicy/Settings/Security")
$xpath
=
"//q1:SecurityOptions"
$securityOptions
=
$xml.SelectNodes($xpath,
$namespaceManager)
foreach
($securityOption
in
$securityOptions) {
Write-Host
"Found '$($securityOption.Display.Name)'"
-ForegroundColor Blue
}
Group Policies, which policies affect the server you are currently logged onto? – see rsop, gpresult
how to all the various Domain Group Policies combine to affect a server? – see rsop, gpresult
$allGPOs
=
Get-GPO
-All
$GPOLinks
=
@()
$i=0
;
$gpocount
=
$allGPOs.Count
foreach
($gpo
in
$allGPOs) {
$i++;
$percentGPOTxt
=
($i/$gpocount).ToString("P")
$gpoName
=
$gpo.DisplayName
Write-Host
"$i
of
$($gpocount)
($percentGPOTxt):
$gponame"
-ForegroundColor Green
[xml]$xml
=
Get-GPOReport
-Name
$gpoName
-ReportType xml
$LinksTo
=
$null
$LinksTo
= $xml.gpo.LinksTo
$j=0;
$linkcount
=
$LinksTo.Count
foreach
($node
in
$LinksTo) {
$j++;
$percentLinkTxtj
=
($j/$linkcount).ToString("P")
if
($null
-ne
$node.SOMName) {
# there always seem to be some null
records that aren't visible in XML file
$SOMPath
=
$node.SOMPath
$domain,
$SOMPathArrayElements
=
$SOMPath
-split
"/"
# convenient one-liner to get everything except $domain;
we dont really care about $domain
$OU
=
$SOMPathArrayElements
-join
"\"
$NoOverride
=
$node.NoOverride
Write-Host
" $j
of
$($linkcount)
($percentLinkTxtj):
$SOMName
$SOMPath
$NoOverride"
-ForegroundColor Cyan
$GPOLinks
+=
New-Object
-TypeName PSObject
-Property
@{
gpoCount
=
$i;
gponame
=
$gpoName;
created
=
$gpo.CreationTime;
modified
=
$gpo.ModificationTime;
owner
=
$gpo.Owner;
id
=
$gpo.Id;
GPOstatus=$gpo.GPOStatus;
description
=
$gpo.Description
LinksCount
=
$j
SOMName
=
$node.SOMName
SOMPath
=
$node.SOMPath
OU
=
$OU
NoOverride
=
$node.NoOverride
}
}
else {
$GPOLinks
+=
New-Object
-TypeName PSObject
-Property
@{
gpoCount
=
$i;
gponame
=
$gpoName;
created
=
$gpo.CreationTime;
modified
=
$gpo.ModificationTime;
owner
=
$gpo.Owner;
id
=
$gpo.Id;
GPOstatus=$gpo.GPOStatus;
description
=
$gpo.Description
LinksCount
=
0;
SOMName
=
$null;
SOMPath
=
$null;
NoOverride
=
$null
}
}
}
}
$GPOLinks
=
$GPOLinks
|
sort gponame, LinksCount |
select gponame, GPOstatus, created, modified, owner,
id, LinksCount, SOMName, SOMPath, OU, NoOverride, description
$GPOLinks
|
ogv
now that we have the $GPOLinks variable, let's get some useful info out of it
no links or GPOStatus -eq “AllSettingsDisabled”
$GPOLinks | ?{$_.LinksCount -eq 0 -or $_.GPOstatus -eq "AllSettingsDisabled"} | sort gponame, LinksCount | select gponame, GPOstatus, created, modified, owner, id, LinksCount, SOMName, OU | ogv
the opposite: have at least 1 link and GPOStatus -ne “AllSettingsDisabled”; only links to OUs, not the whole domain
$GPOLinks | ? {$_.LinksCount -ne 0 -and $_.GPOstatus -ne "AllSettingsDisabled" -and $_.OU -ne ""} | sort OU, gponame, LinksCount | select gponame, GPOstatus, created, modified, owner, id, LinksCount, SOMName, OU, SOMpath | ogv
Local Computer policy, which group policies affect? – see rsop, gpresult
open
gpedit.msc
after making any changes
gpupdate /force
see also group policy management editor
Read a group policy object into an XML variable
[xml]$xml = Get-GPOReport -Name "Srvr-2016" -ReportType xml
add a namespace to be able to process
“q1
” XML elements to get security settings
$namespaceManager
=
New-Object
System.Xml.XmlNamespaceManager($xml.NameTable)
$namespaceManager.AddNamespace("q1",
"http://www.microsoft.com/GroupPolicy/Settings/Security")
$xpath
=
"//q1:SecurityOptions"
$securityOptions
=
$xml.SelectNodes($xpath,
$namespaceManager)
OUs, which GPOs link to – see LinksTo, find for all GPOs
“q1:” tags in GPO XML – see ExtensionData in GPO xml file
registry settings, find for all GPOs
#
Get all the GPOs in the domain
$allGPOs
=
Get-GPO
-All
# Loop through each GPO
$GPORegistrySettings
=
@()
$i=0;
$gpocount
=
$allGPOs.Count
foreach
($GPO
in
$allGPOs) {
$i++;
$percentGPOTxt
=
($i/$gpocount).ToString("P")
$gpoName
=
$gpo.DisplayName
Write-Host
"$i
of
$($gpocount)
($percentGPOTxt):
$gponame"
-ForegroundColor Green
[xml]$xml
=
Get-GPOReport
-Name
$gpoName
-ReportType xml
$registrySettings
=
Select-Xml
-
Xml$xml
-XPath
"//q2:RegistrySettings/q2:Registry"
-Namespace
@{"q2"="http://www.microsoft.com/GroupPolicy/Settings/Windows/Registry"}
$GPOSettingOrder
=
Select-Xml
-Xml
$xml
-XPath
"//q2:RegistrySettings/q2:Registry/q2:GPOSettingOrder"
-Namespace
@{"q2"="http://www.microsoft.com/GroupPolicy/Settings/Windows/Registry"}
$properties
=
Select-Xml
-Xml
$xml
-XPath
"//q2:RegistrySettings/q2:Registry/q2:Properties"
-Namespace
@{"q2"="http://www.microsoft.com/GroupPolicy/Settings/Windows/Registry"}
for
($j
=
0;
$j
-lt
$registrySettings.Count;
$j++) {
$percentRegTxt
=
($j/$registrySettings.Count).ToString("P")
Write-Host
" $j
of
$($registrySettings.Count)
($percentRegTxt):
$($registrySettings[$j].Node.name)"
-ForegroundColor Blue
$GPORegistrySettings
+=
[pscustomobject]@{
gponame
=
$gpoName
Name
=
$registrySettings[$j].Node.name
Image
=
$registrySettings[$j].Node.image
Changed
=
$registrySettings[$j].Node.changed
GPOSettingOrder
=
$GPOSettingOrder[$j].Node."#text"
Action
=
$properties[$j].Node.action
DisplayDecimal
=
$properties[$j].Node.displayDecimal
Default
=
$properties[$j].Node.default
Hive
=
$properties[$j].Node.hive
Key
=
$properties[$j].Node.key
Type
=
$properties[$j].Node.type
Value
=
$properties[$j].Node.value
}
}
$GPORegistrySettings
| sort hive,
key,
Name,
gponame
|
select Hive,
Key,
Name,
gponame,
Type,
Value,
Action,
Default,
DisplayDecimal
|
ogv
report, generate for a single GP
HTML
Get-GPOReport -Name "MonroeDoctrine" -ReportType HTML -Path "$([environment]::getfolderpath("mydocuments"))\MonroeDoctrine.html"
XML
Get-GPOReport -Name "MonroeDoctrine" -ReportType XML -Path "$([environment]::getfolderpath("mydocuments"))\MonroeDoctrine.xml"
rsop – command to pop up a window displaying Result of Policy – see also gpresult /r
Running this command pop-s up GUI window that’s easier to navigate than gpresult’s text output. Not only that, but it indicates which policy affects each setting.
gpresult supposedly returns more complete information than rsop.
If you omit /scope
parameter for gpresult
, it supposedly
will display RSoP data for both the user and the computer. But in practice,
I’ve never seen it return anything for the computer. If I specify
/scope computer
, usually returns ERROR: Access Denied.
list scopes of management (OUs) for all GPOs
$allGPOs
=
Get-GPO
-All
$result
=
@()
$i=0;
$gpocount
=
$allGPOs.Count
foreach
($gpo
in
$allGPOs) {
$i++;
$percentGPOTxt
=
($i/$gpocount).ToString("P")
$gpoName
=
$gpo.DisplayName
Write-Host
"$i
of
$($gpocount)
($percentGPOTxt):
$gponame"
-ForegroundColor Green
[xml]$xml
=
Get-GPOReport
-Name
$gpoName
-ReportType xml
$LinksTo
=
$null
$LinksTo
= $xml.gpo.LinksTo
$j=0;
$linkcount
=
$LinksTo.Count
foreach
($node
in
$LinksTo) {
$j++;
$percentLinkTxt
=
($j/$linkcount).ToString("P")
if
($null
-ne
$node.SOMName
) { # there always seem to be some null records that aren't visible
in XML file
$SOMPath
=
$node.SOMPath
$NoOverride
=
$node.NoOverride
Write-Host
" $j
of
$($linkcount)
($percentLinkTxt):
$SOMName
$SOMPath
$NoOverride"
-ForegroundColor Cyan
$result
+=
New-Object
-TypeName PSObject
-Property @{
"gpoCount"
=
$i
"gponame"
=
$gpoName
"LinksCount"
=
$j
"SOMName"
=
$node.SOMName
"SOMPath"
=
$node.SOMPath
"NoOverride"
=
$node.NoOverride
}
}
}
#if ($i -gt 3) {break}
}
$result
=
$result
|
select gpoCount,
LinksCount,
gponame,
SOMName,
SOMPath, NoOverride
$result
|
ogv
$result
|
Export-Csv
-Path
"$([environment]::getfolderpath("mydocuments"))\GPOAllLinksTo$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"
-Encoding UTF8 -NoTypeInformation
server, which Domain Group Policies affect? – see rsop, gpresult
SOM - scope of management - see scope of management
Servers
which Domain Group Policies affect a server? – see rsop, gpresult
$WmiFilters
=
Get-ADObject
-LDAPFilter
"(objectClass=msWMI-Som)"
-Properties *
$WmiFilters | select @{n="name";e={$_."msWMI-Parm1"}}, @{n="query";e={($_."msWMI-Parm2" -split(";"))[-2]}} | ft -a
The last line above “beautifies” the two parameters so we humans can understand better. If instead we run the simpler “raw” query below, we’d see that the last property buries the query in the second-to-last member of an array separated by semicolons unless we isolate it like the line above above.
$WmiFilters | select msWMI-Parm1, msWMI-Parm2 | ft -a
XML, read Group Policy XML file - see group policy, XML