Tuesday, March 18, 2008

Group Policy Objects and Powershell - 3 Linking the GPOs

I had thought about detailing how you can populate GPOs from backup using powershell, however this has already been covered more than adequately elsewhere, however the script I use looks into the backup location, uses a migration table (to make these GPOs easily pushed into multiple environments), and takes all the GPOs it finds, looks for the GPOs in the Active Directory, then populates them.

Linking them is slightly different, first we pass some variables into the script by using arguments when running the script, it then searches for the GPO in the AD by display name, searches for an the defined OU, then writes the link by writinging the AD attribute 'gpLink' on the OU.


param([string]$domainName,$domainDN,$gpoName,$OU)

# Searches for GPO defined above

$gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object

$gpmConstants = $gpm.GetConstants() # Load the GPMC constants

$gpmDomain = $gpm.GetDomain($domainName, "", $gpmConstants.UseAnyDC) # Connect to the domain passed using any DC

$gpmSearchCriteria = $gpm.CreateSearchCriteria()

$gpmSearchCriteria.Add($gpmConstants.SearchPropertyGPODisplayName, $gpmConstants.SearchOpEquals, $gpoName)

$gpmResultlist = $gpmDomain.SearchGPOs($gpmSearchCriteria) # This will return the GPOs found

foreach ($gpmResult in $gpmResultList)

{

# Finds the OU defined above

$domainpath = "LDAP://" + $domainDN

$domain = [adsi] $domainpath

$searcher = New-Object System.DirectoryServices.DirectorySearcher $domain

$searcher.Filter = $searcher.Filter ='(&(objectClass=OrganizationalUnit)(name=' + $OU + '))'

$OUResult = $searcher.FindAll()

foreach ($result in $OUResult) {$Ou=$result.Path.ToString()}

$gpLinkEntry = "[LDAP://" + $gpmResult.Path + ";0]"

$OUC=new-object directoryservices.directoryentry($OU) #connect to OU

$OUC.Put("gplink", $gpLinkEntry) #Sets GPLink.

$OUC.SetInfo()

}

Group Policy Objects and Powershell - 4 Linking the GPOs - Part 2

In the previous post the method of linking GPOs works reasonably well, however, what if you are linking to an OU that already has a link defined, or you want to link multiple GPOs in a specific order, and you might not want to script them in one at a time, maybe you would want to use a csv file to act as an input file.


First of all you need to pass location of the csv, and the domain name as an argument:-


Param ([string]$File,$domainName)


And as we are going to loop through sections of the script, to help with readability of the script I am going to make use of functions to divide up the workload in the script, fist of all defining a function that looks for the GPO in the AD, and then creates the link by defining a scope of Management rather than writing the gplink attribute into the AD. This allows you to define a link order.


#Function to Create the GPOLink

function CreateGPOLink ($LinkDN,$GPOname,$LinkOrder)

{

$root=[adsi] ""

$gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object

$gpmConstants = $gpm.GetConstants() # Load the GPMC constants

$gpmDomain = $gpm.GetDomain($domainName, "", $gpmConstants.UseAnyDC)


# Create the GPO Searcher

$searcher = $gpm.CreateSearchCriteria()

$searcher.Add( $gpm.GetConstants().SearchPropertyGPODisplayName, `

$gpm.GetConstants().SearchOpEquals, $GPOname )

$GPOlist = $gpmDomain.SearchGPOs( $searcher )

#Define the GPO Scope Of Management

$LinkDN

$gpmSOM = $gpmDomain.GetSOM($LinkDN)


# Create the actual link

$GPMlink = $gpmSOM.CreateGPOLink($LinkOrder, $GPOlist.Item(1) )}


The next function needs to be a function that imports the csv file, and reads it line by line, calls the CreateGpoLink function by passing it variables from the csv file where the variable 'type' from the csv is equal to GPOLink, the other variables are LinkDN, GPOname, and LinkOrder – I will show you the format of the csv at the end.


function Import-GPOLinks([string]$File)

{

Import-Csv $File foreach-object { if ($_.type -eq "GPOLINK") {CreateGPOLink $_.LinkDN $_.GPOname $_.LinkOrder}}

}


Finally we need to call the Import-GPOLinks function and passing it the csvfile location from the arguments passed with the script.


Import-GPOLinks $File


The CSV in this case will need to look something like this:-

type,LinkDN,GPOname,LinkOrder

GPOLink,"ou=Architecture,dc=philtest,dc=pri",DenyUserRightsPolicy_C1.0,1

GPOLink,"ou=Architecture,dc=philtest,dc=pri",AllowUserRightsPolicy_C1.0,2

GPOLink,"ou=Architecture,dc=philtest,dc=pri",AllMembersRestrictedGroupsPolicy_C1.0,3

GPOLink,"ou=Architecture,dc=philtest,dc=pri",MemberServerBaselinePolicy_C1.0,4

GPOLink,"ou=Architecture,dc=philtest,dc=pri",LogonBannerPolicy_C1.0,5

GPOLink,"ou=Architecture,dc=philtest,dc=pri",TerminalServicesPolicy_C1.0,6

GPOLink,"ou=Domain Controllers,dc=philtest,dc=pri",DomainControllerPolicy_C1.0,1

GPOLink,"dc=philtest,dc=pri",DomainPolicy_CU1.0,1


As you can see from the final entry this allows me to link to the route of the domain as easily as I can to a specific GPO. You might wonder why I bothered to define a 'type' entry in the csv, this is because in my case I use another version of the script I used in the GPO creation post, and I use the same CSV file with a different 'type' entry of 'GPO' so that the script can pick out the relevant entries, this new version looks like this using much the same method as above:-


Param ([string]$File,$domainName)

function creategpo($gponame)

{

$gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object

$gpmConstants = $gpm.GetConstants()

$gpmDomain = $gpm.GetDomain($domainName, "", $gpmConstants.UseAnyDC) # Connect to the domain passed using any DC

$gpmGpo = $gpmDomain.CreateGPO()

$gpmGpo.DisplayName = $gponame

}

function Import-GPOList([string]$File)

{

Import-Csv $File foreach-object { if ($_.type -eq "GPO") {creategpo $_.GPOname}}

}

Import-GPOList $File