How do I enumerate GPOs linked to an OU in Active Directory?

How would I find a computer object in AD, determine the computer object's OU, and enumerate the GPOs that are specifically linked to that OU?

I received an audit script request from Management that I've been able to translate into the following request.
"Write a script that can do the following:
1.  Search AD for a computer object
2.  Identify the OU of the computer object
3.  Enumerate the GPOs linked to the identified OU
4.  Determine the Global Group(s) designated in the security filter of the GPO
5.  Verify that the members of the Administrator group belong to one of the identified Global Groups"

This was a fairly liberal translation and is significantly less ambiguous than the original request.  Steps 1 and 2 are fairly simplistic by my standards, as well as step 5.  It is those pesky steps 3 and 4 that have me browsing the web, watching webcasts, and finally pandering to those who have more scripting mojo than myself.

Simply put, how do I use a computer object's ADsPath to query AD to find GPOs linked to the computer object's OU?  I'm only interested in the GPOs linked directly to the OU and none of the GPOs linked higher up in AD.  Thanks!
Who is Participating?
gustavwindConnect With a Mentor Commented:
Not pretty or robust but gets the job done.  Give the vbScript the DN of the OU you need to check.  Enclose it in quotes if it has spaces.  Outputs a comma delimited list of the GPO name, the GUID, and shows whether the link is active.  
strOU = WSCript.Arguments(0)	' DN of the OU enclosed in quotes
' Configure ADODB ADsDSO connection
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 3000
' Find the OU
objCommand.CommandText = _
    "<LDAP://" & strOU & ">;(objectClass=organizationalUnit)" & _
Set objRecordSet = objCommand.Execute
strGpLinks = objRecordSet.Fields("gpLink").Value
intCnt = 0
' Parse the gpLink
Do until strGpLinks = ""
	i = instr(strGpLinks,"]")
	strGpoDn = mid(strGPlinks,2,i-2) 'DN for LDAP query
	strGpLinks = mid(strGPLinks,i+1) 'strip it off the gpLink string
	' Use the DN to find the GPO object
	objCommand.CommandText = "<" & mid(strGpoDn,1,len(strGpoDn)-2) & ">;" & _
	set objRecordSet = objCommand.Execute
	strGPOName = objRecordSet.Fields("displayName").Value
	strGPOGuid = mid(strGpoDn,11,38)
	if mid(strGpoDN,len(strGpoDn),1)="0" then
		strGpoLinked = "*Linked*"
		strGpoLinked = "unlinked"
	end if
	wscript.echo chr(34) & strGPOName & chr(34) & "," & strGpoLinked & "," & strGpoGuid
	intCnt = intCnt + 1
wscript.echo intCnt

Open in new window

Chris DentPowerShell DeveloperCommented:

I can't help but wonder exactly what an audit like this is expected to show... To me it's approaching GP application from the wrong direction and ignores the existing tools (such as RSOP.msc, GPResult and the Group Policy Management Console) which can easily retrieve much of the above.

Still... I know where the items you're after are set.

The Policies linked to a specific OU are defined in the GpLink attribute on an OU. That attribute contains the LDAP paths for each explicitly linked policy (but doesn't account for inheritance). Unless I find a better way that leaves you checking that up the tree as well.

Using each of those paths would let you get back to the policy name, the displayName attribute on the linked policy.

The security filter is based on all objects that have the "Apply Group Policy" right on the policy meaning you'd need to read and interpret the security descriptor. By default that's just Authenticated Users.

FieosAuthor Commented:

I was instructed to write a script that reads a list of host names, for each host it determines which OU in which the host resides, it determines what GPOs are linked to that OU, it then enumerates the Administrators group on the server and verifies that the account is a member of one of the groups identified in the security filter of the applied GPO.  Example output to an XLS would look like this:

Hostname     OU                    Linked GPO                Account         GPO applied to user
ServerA       Infrastructure   Admin_Lockdown      User01           Yes

If you know of a better way to provide this information, I appreciate any feedback.  Your GpLink information should be a help already as I don't have a good understanding of AD schema.  Right now I'm pulling the distinguished name and I figure I'll have to clean that string up to query OU information.  I hope this is a report that they actually use!

Thanks again!

Never miss a deadline with

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Chris DentPowerShell DeveloperCommented:

Fair enough :) My opinion on the approach isn't really relevant if you have to produce the script regardless.

The OU is a bit of a tricky one to get, in quite a lot of cases it does end up being easier parsing the name out of the string. The only way we have of getting that explicitly in code is by calling a "Parent" method on an object.


Set objComputer = GetObject("LDAP://CN=MyPC,OU=Somewhere,DC=mydomain,DC=com")
strOU = objComputer.Parent

Not exactly neat, and quite heavy on AD connections if you have a lot to check.

I'd like a little time to think about this one, it's a long way from being trivial.

FieosAuthor Commented:
Well, I've made a fair amount of progress.  I can find the OU of the computer and enumerate the linked GPOs.  I'm trying to figure out how to enumerate the members of the security filter.  I see the GetSecurityInfo( ) Function but I'm not sure how to enumerate the data.  I believe that is the function that contains the accounts in the security filter, but I've also seen that it holds the access lists to modify the GPO.  Do you happen to know what information is contained?  I've seen the .add and the .remove but I don't see anything to enumerate the contents.
Chris DentPowerShell DeveloperCommented:

Hmm, I wonder. Would it be bad to attempt to convince you to switch to PowerShell for writing this kind of thing?

It's just permissions in VbScript are a lot of hard work. In PowerShell we can create some really pretty reports.

That might fall apart if the script has to be portable.

FieosAuthor Commented:
I haven't played with PowerShell scripting.  I was under the impression I couldn't use it against 2003 servers.  Is that not the case?   We have a MS trainer coming in a few weeks to train us on the wonders of PowerShell; perhaps I should get a head start.
Chris DentPowerShell DeveloperCommented:

You can, I used it extensively against my domain which is also 2003 :)

If you go down that road it would probably also be a good idea to get this:

They're free, and we could use something like the Get-QADPermission cmdlet for this.

Chris DentPowerShell DeveloperCommented:

If we're going to look at that path I think I'll see if one of the other experts is available to take a look at this. He's much better at PowerShell than I and might have some insights that will make this a lot less bother :)

FieosAuthor Commented:
I appreciate the help, and your continued support.  
Using powershell with the free GPO cmdlets from and the free AD cmdlets from this task is trivial. If you would like I can post an example.
FieosAuthor Commented:
I would definitely appreciate an example if you have one available.  I'm completely new to powershell.
Can you clarify point 5?
FieosAuthor Commented:
5.  Verify that the members of the Administrator group belong to one of the identified Global Groups"

Pull the members/groups of the local administrators group on the server.  Identify (Yes/No) as to if the members of the local administrators group on the server are members of the group(s) identified in the security filter of a GPO.

Server = Myserver has two groups in the administrators group:  Group1 and Group2
Determine in a yes/no manner if those groups are members of groups identified in a GPOs security filter.  

This is to basically verify that we do have this user/group in the administrators list, but they are a member of a group that is identified in the security filter of GPO applied to the OU of which the server resides.  

That help?
I will work on part 5... I am still not sure I get the point, but here is something to play with
add-pssnapin SDMSoftware.PowerShell.GPMC -ea 0
add-pssnapin Quest.ActiveRoles.ADManagement -ea 0
#1.  Search AD for a computer object
$CompObj = Get-QADComputer $Computer
#2.  Identify the OU of the computer object
$OU = invoke-expression "'$($CompObj.distinguishedName)' -replace 'CN\=$Computer,',''"
#3.  Enumerate the GPOs linked to the identified OU
$GPLinks = Get-SDMgplink -scope $OU -native
#4.  Determine the Global Group(s) designated in the security filter of the GPO
foreach($link in $GPLinks)
    $groups = Get-SDMgpo -GPOID $link.GPOID | Get-SDMgpoSecurity | %{$_.ToArray()} | %{$_.Trustee}

Open in new window

FieosAuthor Commented:
Thanks, sorry for the late follow-up
All Courses

From novice to tech pro — start learning today.