AD Remediation: GPOs

This is one of a series of posts about fixing problems that have accumulated in an old instance of Active Directory (AD). In this case, it is about Group Policy Objects (GPOs).

GPOs are as old as AD. They were introduced as a partner technology back in the year 2000. Group Policies are configurations that apply to a Windows computer, and GPOs are objects that contain a collection of policies. When a computer account or user account authenticates to the domain, it obtains the GPOs that apply to it and sets the policies contained in the GPOs.

Over the years, you may have accumulated hundreds of GPOs. You can see how many you have with this cmdlet: (Get-GPO -All).count. In an ideal world, someone would have tidied up continuously, but often, in my experience, that is not part of anyone’s role. Tidying up retrospectively can be an enormous task.

Why is it difficult? Surely you just need to look at each GPO and decide if it is still needed or not. But GPOs don’t work like that. As you might expect, there is a great deal of flexibility and complexity in how configurations are applied: precedence; inheritance; blocking; enforcement; ordering; merging; loopback processing; item-level targeting. To tidy up the GPOs, you first need to unravel all the complexity in how they have been created and applied over many years.

Why do it at all? In the end, a computer applies policies based on an algorithm to determine which ones should apply. You can see the winning configurations in a Resultant Set of Policy (RSoP), either in the GUI or with PowerShell Get-GPResultantSetOfPolicy -Computer [name of a domain computer to test] -User [name of a user to test] -ReportType [html or xml] -Path [path to the report]. So, arguably, if the RSoP is what you want, it doesn’t matter how it is achieved. Certainly, from a security point of view, you would audit the end result and not how it is achieved.

The main reason to tidy up GPOs is an operational one. A large number of accumulated policies is hard to understand. It is hard to make small changes without error or unintended consequences. If it takes to long to make changes, it could be because the existing GPOs are too complicated to understand.

Who is this a problem for? The content of GPOs belongs to individual service owners, not to the directory service owner. The directory is just the vehicle for delivering configurations, just as a network is the vehicle for delivering email. So you could ask the service owners to tidy up their policies. But it is the lack of ownership that has caused the problem in the first place.

If you start to tidy up policies, but are not the owner of the configuration (i.e. the service owner), it is important to recognise that the objective has to be to maintain the same RSoP. If you start to change the RSoP, then you are engaged in a service design, which is a quite separate matter.

This brings us back to the idea that you can avoid much of this by migrating to cloud-only services. If your devices are managed by Intune, and your user accounts are in Entra ID (whether hybrid or not), then all the GPOs applying to them in AD are redundant. You may still have GPOs, for the on-premises services, but far fewer and far easier to administer.

If you do decide to go ahead, here are my steps and methods to do it:

  1. Find and unlink all the redundant GPOs, being those with: no Apply permissions; applying only to unknown SIDs (representing a deleting account or group); GPO disabled; configuration disabled; link disabled; no link; obsolete WMI filter (for example, an OS version that you know is no longer used).
  2. Unlinking a GPO allows you to restore it quickly if you need to. You can make a backup and delete it when it has been unlinked for a while. You can back up and delete any GPOs that are already unlinked. This is a progressive action. In your directory clean up, as you disable unused accounts, and delete empty groups, and delete the resultant empty OUs, you will have more redundant GPOs.
  3. Fix the GPOs that sit outside the OUs where your computer and user accounts are. This will avoid the need for blocking inheritance.
  4. Find the RSoP for each group of accounts. Rationalise the GPOs in the RSoP. By “group of accounts”, I mean each large cluster of user and computer accounts. The biggest one, of course, will be a standard user on a standard desktop. Another might be for virtual desktops. As you get to smaller and smaller clusters (e.g. administrators on file servers), it can be easier just to examine the GPOs manually.
  5. Deal with each of the policies that is filtered on a subset of accounts. Some of them may be needed, for example to configure an application. Some may be obsolete policies developed for testing and never used.

In Step 1, I use scripts based on PowerShell Get-GPO and Get-GPOReport. Get-GPO only returns a set of meta data about the GPO itself, not the settings in the GPO. Get-GPOReport returns the configurations of the GPO as XML, which can be parsed to find what you are looking for. Get-GPPermission gets the permissions on a GPO, which you can filter to find who the GPO is applied to, with the GPOApply permission. Get-GPInheritance gets the GPOs that are linked to a specified OU, together with the order in which they are linked. You can see examples of my discovery scripts here: obsolete GPOs, Apply permissions, and GPOs by OU.

In Step 2, you can script a backup of the GPO before unlinking or deleting it, with Backup-GPO -Guid [GUID of the GPO] -Path [path to the backup directory]. I always use the GUID for these actions, in case the object has been deleted and replaced with another of the same name.

In Step 3, the problems are distinct and separate:

  • The Default Domain and Default Domain Controllers GPOs should contain only the settings that are in the defaults created with the domain. You can customise each of the settings, but should not add other settings. These GPOs are not the place to add settings that you want to apply to all computers, or all users, or all domain controllers: those should be in separate GPOs. There is an obscure reference to this in the documentation for dcgpofix, which is a utility to recreate the default GPOs.
  • GPOs in the root of the domain are a legitimate way to configure settings for all computer accounts or all user accounts. GPOs here will apply to accounts in the default Computers and Users containers. Because they are containers and not OUs, you cannot add GPOs to these directly. But they do inherit from the root.
  • But, if you don’t need to apply GPOs to these default containers, and if you find you are blocking inheritance to avoid GPOs in the root, then the solution is to unlink them from the root and apply them only where they are not already blocked.

In Step 4, the RSoP will show you the “Winning GPO” for each setting. If you take each winning setting, and only those, and put them in a new set of GPOs, you will be able to replace all the existing GPOs in the RSoP. If you make a copy of the existing GPOs, you can edit these to keep only the winning settings. If you want to re-organise the settings into a more logical collection of GPOs, you can create new ones and move the settings into them.

You can cross-check the winning policies by using the Microsoft Policy Analyzer, part of the Microsoft Security Compliance Toolkit. Policy Analyzer will not show you the winning policy. But it will show every separate policy in the GPOs in an Excel spreadsheet, together with every duplicate and conflict. If you load Policy Analyzer with every GPO that applies to all your target accounts, and if you know the winning policy from the RSoP, then you can identify all of the duplicates and conflicts that should be removed.

In Step 5, you will have a long tail of GPOs that apply to only a subset of computer or user accounts, based on filtering of the GPO Apply permission. These may be accounts with an allowed exception, or to configure an application. Mostly, you will want to keep all of these.

But you will need to be careful with them. The settings may conflict with other policies, or with the RSoP for the same accounts. In this case, they will rely on ordering. Ordering is a subtle property. It is not a property of the GPO itself. It is a property of the link. It can be obtained by Get-GPInheritance for a set of GPOs either linked directly to an OU, or inherited by it.

Just because a GPO has a higher precedence (lower link order) does not mean it needs or uses the order to take effect. The order only matters if there is a conflict. You could use Policy Analyzer to detect the conflict. But, if you use naming and granularity to specify the purpose of each GPO, it should be easy to identify where you have a potential conflict.

My preference is break out policies that have exceptions as separate GPOs: both the rule and the exception. For example, if you have a rule that most people cannot write to USB, and an exception that allows some people to write, then you can have one GPO for the rule. This rule can be applied to authenticated users, ensuring it is always the default in the absence of an exception. You can then use a Deny Apply for the group of people who are exempt from this rule; and, optionally a second GPO to allow write. You don’t need this rule if it is the default setting in Windows, but creating it means that it cannot be accidentally changed. By applying this GPO to the same group as the Deny Apply for the main rule, you guarantee an account must be either one or the other, and never “Not configured”. Then you don’t rely on ordering, which can easily be changed unintentionally.

In Step 5, too, you can deal with GPOs that are applied only to what looks like test accounts; for example, a few users or computers by name, or a security group that looks like a test group. If you use the script Get-GPOApply to show every Trustee for every GPO, you can filter on the permissions that look doubtful.

You can see that, even with scripts and tools, if you have many redundant GPOs there is a large amount of work in rationalising them. There is also a significant risk of unintended impact, no matter how careful you are. For this reason, you need to be very sure you want to go ahead, rather than migrating to cloud-only services with no GPOs.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.