Ah, Group Policy objects. Ever since their introduction in Windows 2000, most companies have been gradually building a larger and larger library of GPOs, each applying a larger and larger number of settings to users and computers. Today, we rely on them to configure security-sensitive settings, to mapping drives and printers, to configuring how software applications look and behave.
Unfortunately, the native tools for GPO administration aren’t full-featured, meaning that a robust GPO-using environment can sometimes have its work cut out for it.
Probably one of the toughest things to accomplish with the native tools is a comparison of a GPO. There are a variety of situations in which you might need to do so:
Figure 1 The Group Policy Management Console
The native graphical management console – the Group Policy Management Console, or GPMC, to be specific – doesn’t include comparison capabilities. This is where I’d normally turn to PowerShell, and Windows Server 2008 R2 (and Windows 7) offer a GroupPolicy module. In it, the Get-GPRegistryValue cmdlet would seem to offer a technique. If it was capable of getting every value (setting) from a GPO, then I could use it to load two different GPOs and compare them using PowerShell’s Compare-Object cmdlet. Sadly, Get-GPRegistryValue can’t recursively read every setting out of a GPO. For example, it could do this:
Get-GPRegistryValue –Name 'CorpGPO' –Key HKCU\Software
That should get every setting configured under HKEY_CURRENT_USER\SOFTWARE, but in fact won’t work. Time to dig a little deeper.
The GroupPolicy module also includes a Get-GPOReport cmdlet, which looks promising. It can generate results in both XML and HTML; while HTML is easier to read, it won’t be so useful for making an automated comparison possible. We’ll focus on XML instead.
Get-GPOReport –name 'CorpGPO' –ReportType XML
That certainly displays the information we’re after – a whole bunch of it, in fact. Let’s try using it to compare two GPOs:
PS C:\> Diff (Get-GPOReport -Name 'CorpGPO' -ReportType XML) (Get-GPOReport -Name 'Default Domain Policy'
Figure 2 the Compare-GPO PowerShell Script
Unfortunately, the output consists of the entire XML document – the report XML just isn’t designed for a straightforward comparison like this. Fortunately, Microsoft’s Scripting Guys offer a Compare-GPO script at https://gallery.technet.microsoft.com/ScriptCenter/18dea308-4faf-44bf-9e1c-e83d47edb866/. It does the work of comparing that complex XML produced by Get-GPOReport. The output looks something like Figure 3.
Figure 3 Results of the Compare-GPO Script
This is indicating that both compared GPOs set a particular setting – in this case, AuditLogRetentionPeriod and RetentionDays. This still isn’t ideal output. For example, while both GPOs configured both of those settings, they each set them to different values, which isn’t shown here. Also, the report doesn’t indicate which audit log’s retention period was set. Browsing through the GPO, I can see that it’s the Security log, but it’s a lot of manual effort to discover that fact.
There’s also the problem of getting to the GPOs in the first place. The script I used above assumes that both GPOs you want to compare live in the same domain; that won’t always be the case. The GPOs also have to be loaded into a domain controller, although they needn’t be linked to anything (meaning they could just be sitting there, in active). If you want to compare a backed-up GPO to an active version of the same one, it might be tricky to get them both loaded into a domain controller at the same time. Now, you could manually run the XML-generation command for each GPO:
(Get-GPO -Name $gpo -Domain $domain -Server $server).GenerateReportToFile("xml",$path)
And then use the script’s Compare-GPOAsXML function manually. That would let you pull XML reports from any GPO in any domain, and then bring the two XML files together to compare them directly. Again… it starts to add complexity to the situation.
Comparing GPOs is actually a pretty common need, one that – as you’ve seen – isn’t well-met by the native Windows tools. Anytime you see “common need” compared with “not done well by the native tools,” you can bet that someone outside Microsoft has taken a stab at solving the problem. That’s certainly the case for GPO comparison: Punch “compare GPO tool” into your favorite search engine and you should generate a few useful hits.
As you’re looking at such tools, there are a few things you’ll want to keep in mind. After all, if you’re going to be bringing in outside software, you might as well choose a tool that is most likely to meet all of your needs. Here’s my “wish list:”
You may have some other capabilities that you’d like in a GPO management or comparison tool; add those to your own personal wish list and see if you can find a tool that handles it all.
Well, sort of. If you have a change auditing solution that’s capturing changes to GPOs as they’re made, that can definitely be useful for troubleshooting, but those audit reports don’t necessarily eliminate the need to have a good comparison tool. After all, GPOs change over time, right? You don’t want to have to dig through months of audit reports to find all of the changes to a GPO! It’d be much more efficient to just store a “baseline” copy of a GPO, and then compare it to the “current version” anytime you want to see a complete list of differences.
In fact, that’s a good recommendation to end with: Make a backup of all of your GPO objects, as they currently exist, and treat those as a baseline. That backup can be the entire GPO file, or maybe an XML representation generated by a PowerShell cmdlet. The idea is to have a baseline file that can be quickly and easily compared to the GPO’s current version, so that you can quickly spot changes. Whenever an authorized change is made to a GPO, update your baseline to reflect the most up-to-date settings.