Tracking Windows Group Policy Changes With PowerShell

This video tutorial explains how you can use PowerShell to identify changes in Group Policy settings.

Brien Posey

August 22, 2023

In this tutorial, Brien Posey explains how to use PowerShell to track Group Policy drift.

Group Policy drift is when an organization’s Group Policy settings change over time, causing differences between how things are supposed to be set up and how they actually are. Administrators can monitor these changes with PowerShell.

The following transcript has been lightly edited for length and clarity.


Brien Posey: Hello, greetings, and welcome. I'm Brien Posey. In this video, I want to show you how to use PowerShell to track Group Policy drift. So, let's go ahead and get started.

As you can see, I have an elevated PowerShell window open. I'm going to create a report file that shows the current state of our Group Policy.

Now, there are many ways that we could do this. We could track individual Group Policy objects. We could track the resultant set of policies. For this video, I'm going to use the Default Domain Policy.

Create the Baseline Report

So, the command that I'm going to use is Get-GPOReport.

From there, we have to provide the name of the Group Policy object that we want to report on. As I mentioned, I'm going to use the Default Domain Policy. So, I'm going to type -Name, and then, in quotation marks, Default Domain Policy.

Get-GPOReport -Name “Default Domain Policy”

Next, we have to tell PowerShell what type of report we want to create. I'm going to create an XML-based report, so I'll type -ReportType XML.

Get-GPOReport -Name “Default Domain Policy” -ReportType XML

Next, we have to provide the path where the report is going to be stored. We have to provide PowerShell with a file name. So, I'm going to type -Path, and then, in quotation marks, I need to enter the path and file name. I'm going to use C: DataBefore.xml.

Get-GPOReport -Name “Default Domain Policy” -ReportType XML -Path “C:DataBefore.xml”

Now, you could call the file anything that you want. The reason why I'm using the name Before.xml is that, for this video, I'm going to create a baseline report, which is the one that I'm about to create right now. Then I'm going to make a change to the Group Policy object, and then I'm going to create another report and then we'll compare the two.

So, I'm going to go ahead and press Enter. It will take just a second to create the report. And it looks like the report has been created. And if you're curious about what that report looks like, I'm already in the Data folder so I'm just going to type:

Type Before.xml

And you can see the contents of the file. This file is in JSON format. If I scroll up, you can see all the various items that exist within that file.

Modifying the Group Policy Object (To Simulate Policy Drift)

The next thing that I'm going to do is I'm going to modify the Group Policy object.

I'm going to switch over to the Group Policy Management Editor. I'm going to modify the “Do Not Allow Encryption on all NTFS Volumes” setting. The reason why I'm choosing this setting out of all the various Group Policy settings is simply that it's not going to be disruptive to anything that I'm about to show you. In the real world, of course, you would track whatever Group Policy settings apply to your environment.

So, I've already created a file that shows my baseline Group Policy settings. So now I'm going to modify this Group Policy setting as a way of simulating policy drift.

I'm going to go ahead and double-click on the setting. Then I'm going to enable this and click OK. So, the Group Policy setting has been enabled. I'll go ahead and close this out.

The next thing that I need to do is to update the machine so that it has the latest Group Policy information. And the way that I'm going to do that is to type:

Gpupdate /force

Gpupdate is short for Group Policy update.

That's going to update the machine’s Group Policy information. This can take just a moment to complete.

Protect the Baseline Report

Before I move on, I want to make the report file that we've created Read Only. Remember, this file is going to act as our baseline. Anytime that we suspect that Group Policy drift may have occurred, we want to be able to refer back to this file. We don't want that file to be accidentally modified or erased. So, if we want to flag this file as Read Only, we can rely on an old DOS command called attrib.

So, the command is attrib, and then whatever the file name is. In this case, the file was called Before.xml. Then we type +R. The +R adds the Read Only attribute.

attrib before.xml +R

I'll go ahead and press Enter. And there's no visible output. But if I were to type attrib, and then the file name without any kind of attributes specified, we can see that the Read Only attribute has been applied. And if we wanted to put that to the test, I can even try erasing the file, and I get an error message. The reason for that is that the file is Read Only.

Incidentally, if you wanted to make the file not Read Only sometime in the future, what you would do is you would type the same command as before, only you would change the +R to a -R.

attrib before.xml -R

Now the Read Only attribute is gone. But for right now, I'm going to go ahead and put the Read Only attribute back. And again, this is not a required step. It's simply there as a means of protecting yourself.

Create the New Report

The next thing that I want to do is create another report because, remember, we made that change to the Group Policy settings.

So, what I want to do now is capture the current state of our Group Policy. To do that, I'm going to use the same command that we used before. The only difference is that instead of calling this file Before.xml, I'm going to call it After.xml.

Get-GPOReport -Name “Default Domain Policy” -ReportType XML -Path “C:DataAfter.xml”

I'll press Enter. So now, the file has been created. And if we look at the contents of the folder, we can see that we now have a Before.xml and After.xml file. And you'll even notice that the file sizes are a little bit different from one another.

Compare the Reports

The last step in the process is to compare these two files to find out if Group Policy drift has indeed occurred, and, if it has occurred, what has changed.

To do that, we can use a PowerShell cmdlet called Compare-Object. And I'm going to enter the Compare-Object cdmlet.

Then we have to tell PowerShell what we want to use as a reference object. Now, remember, we created that Before.xml file as a baseline reference file. We'll use that as our reference object. So, I'm going to type -ReferenceObject.

Compare-Object -ReferenceObject

Then I'm going to type open parentheses, Get-Content -Path, and then the path and file name to our reference file, which is C:dataBefore.xml, and close parentheses.

Compare-Object -ReferenceObject (Get-Content -Path C:dataBefore.xml)

Then I have to do the same thing for our difference object. The difference object is going to be the After.xml file that we created a moment ago. So, I'll type:

-DifferenceObject (Get-Content -Path C:DataAfter.xml)

So far, the command should look like this:

Compare-Object -ReferenceObject (Get-Content -Path C:dataBefore.xml) -DifferenceObject (Get-Content -Path C:DataAfter.xml)

And then I'm going to use the pipe symbol, then type Select-Object. There are two particular objects that I want to look at. I want to look at the InputObject and the SideIndicator. The SideIndicator is a mechanism that tells us which file was different. So, I'm going to type InputObject and then SiteIndicator.

Compare-Object -ReferenceObject (Get-Content -Path C:dataBefore.xml) -DifferenceObject (Get-Content -Path C:DataAfter.xml) | Select-Object InputObject , SideIndicator

I'll press Enter, and here we see our output.

Now, in this case, the SideIndicator is suppressed. The reason for that is that only one file had any changes in it. On the other hand, if both the reference object and the difference object contain changes, then the SideIndicator would tell us which change belongs to which file. In this case, there was only one change, so the only thing that we see listed is the InputObject.

Interpret the Results

Let's look at what we've got here. Beneath the InputObject, we have the ModifiedTime, so we can see when the changes occurred. You can also see the ReadTime and VersionDirectory.

When we scroll down just a little bit, things start to get interesting. Here we have a policy change. So, the name of the policy is “Do Not Allow Encryption on All NTFS Volumes.” You can see that policy is now enabled, whereas it wasn't before.

We also have an explanation of the policy. So right here you can see: “Encryption can add to the processing overhead of filesystem operations. Enabling the setting will prevent access to and the creation of encrypted files.”

You can see that this policy setting is supported on Windows Server 2008 R2 or Windows 7 and higher.

Then you can even see the category. You can see that this setting is found under System/Filesystem/NTFS.

We have all this information regarding which policy setting was modified and when, and we did every bit of that from PowerShell.

So, that's how you can use PowerShell to track Group Policy drift.

I'm Brien Posey. Thanks for watching.

About the Author(s)

Brien Posey

Brien Posey is a bestselling technology author, a speaker, and a 20X Microsoft MVP. In addition to his ongoing work in IT, Posey has spent the last several years training as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like