PowerShell Script to Copy OUs and Groups from AD Including Group Membership

There is an updated version of this AD Administration PowerShell script that is much simpler.

I couldn’t find a clean method to export group membership from AD. LDIF notoriously does not allow importing the MemberOf attribute, so I began looking for a way through PowerShell. I found a method using Quest’s AD Tools SnapIn. The code below will grab the Name, MemberOf, DN and edmPolicy (used in CAE) from an existing OU and import it into a new domain:

#Requires -pssnapin Quest.ActiveRoles.ADManagement
#Script Requires ActiveRoles Management Shell for Active Directory from http://www.quest.com/powershell/activeroles-server.aspx

#OU to export from
$ExportOU = "contoso.com/APPLICATIONS/App"
#Existing Domain to pull structure from
$Domain = "DC=contoso,DC=com"
#Domain to receive new structure
$NewDomain = "DC=slyckstyx,DC=com"
#Domain controller to receive new AD structure
$ChildDC = "dc01.slyckstyx.com"

#Connect to the logged in domain
connect-qadService

#Show progress bar immediately
Set-QADProgressPolicy -ShowProgress $true -ProgressThreshold 0 | Out-Null

#Discover OU tree
$OUList = get-QADObject -SearchRoot $ExportOU -type organizationalunit

#Discover all Groups in the defined OU then collect these properties: edmPolicy,Name,memberof,DN
$Collection = Get-QADGroup -SearchRoot $ExportOU -IncludeAllProperties | select-object -Property edmPolicy,Name,memberof,DN

#Show how many groups were collected (should be 166)
Write-Host "Total Groups:" $Collection.count

#Loop through the collection to deserialize the memberof array; the array values will be placed into a string separated by semicolons in order to split during the import script
ForEach ($grp In $Collection)
 {
  #Reset this variable before looping again
  $StringMember = ""
  $StringedmPolicy = ""

  #Put a semicolon behind each value of the memberof and edmPolicy array for each group collected
  foreach ($member in $grp.memberof) { $StringMember += "$member;" }
  foreach ($policy in $grp.edmPolicy) { $StringedmPolicy += "$policy;" }

  #Replace the parent Domain with the New Domain for each value
  $StringMember = $StringMember.replace($Domain, $NewDomain)
  $StringedmPolicy = $StringedmPolicy.replace($Domain, $NewDomain)
  $grp.DN = $grp.DN.replace($Domain, $NewDomain)

  #Replace the memberof and edmPolicy arrays with our newly created strings; also remove the last semicolon because it's an extra
  if ($grp.memberof.length -eq 0) { $grp.memberof = "" }
  else { $grp.memberof = $StringMember.substring(0,$StringMember.length-1) }
  if ($grp.edmPolicy.length -eq 0) { $grp.edmPolicy = "" }
  else { $grp.edmPolicy = $StringedmPolicy.substring(0,$StringedmPolicy.length-1) }

  #put the strings back into the array for import
  $grp.memberof = $grp.memberof.split(";")
  $grp.edmPolicy = $grp.edmPolicy.split(";")
 }

######################################################################IMPORT######################################################################
#Connect to Child DC
connect-qadService -service $ChildDC

ForEach ($OU in $OUList)
 {
  #Remove the OU name from its DN to create the ParentContainer attribute
  $ParentCN = $OU.DN.TrimStart("OU=" + $OU.Name)
  $ParentCN = $ParentCN.Substring(1)

  #Change the Domain to new domain
  $ParentCN = $ParentCN.replace($Domain, $NewDomain)

  #Add the OU to the new domain
  new-qadObject -ParentContainer $ParentCN -type 'organizationalUnit' -NamingProperty 'ou' -name $OU.name
 }

#Loop through each group and create the group
ForEach ($grp In $Collection)
 {
  #Remove the group name from its DN to create the ParentContainer attribute
  $ParentCN = $grp.DN.TrimStart("CN=" + $grp.Name)
  $ParentCN = $ParentCN.Substring(1)

  #Determine if there are any edmPolicies to include, then create the new groups
  if ($grp.edmPolicy) { new-qadGroup -ParentContainer $ParentCN -name $grp.Name -samAccountName $grp.Name -ObjectAttributes @{edmPolicy=$grp.edmPolicy} }
  else { new-qadGroup -ParentContainer $ParentCN -name $grp.Name -samAccountName $grp.Name }
 }

#After creating the groups, add their memberof attributes
ForEach ($grp In $Collection)
 {
  echo $grp.Name
  if ($grp.memberof) { Add-QADMemberOf -identity $grp.Name -group $grp.memberof }
 }

2 Comments

Leave a Reply