Last week I came across a situation where I needed to copy Active Directory groups (including members) as new groups.

Scenario

Suppose we want to clone the “SG-Test1” and “SG-Test2” groups

Windows – Powershell script to clone AD groups - Old Groups

We need two groups (“SG-NewTest1” and “SG-NewTest2”) to be created with the same members included

Windows – Powershell script to clone AD groups - New Groups

Using this powershell scripts you can either clone a single group a list a groups (OU, scope and members remain the same).

Powershell – Clone single group

Example usage

Simply pass the group to clone and the name of the new group that will be created.

PS D:\SCRIPTS> .\Clone_Group.ps1 <OLD GROUP NAME> <CLONED GROUP NAME>

For example:

PS D:\SCRIPTS> .\Clone_Group.ps1 SG-Test1 SG-NewTest1
Created new Group SG-NewTest1 (path OU=MyGROUPS,DC=domain,DC=com)

PS D:\SCRIPTS> .\Clone_Group.ps1 SG-Test2 SG-NewTest2
Created new Group SG-NewTest2 (path OU=MyGROUPS,DC=domain,DC=com)

Code (Clone_Group.ps1)

Download the code of Clone_Group.ps1

Param(
  [string] $OLD_GROUP_NAME,
  [string] $NEW_GROUP_NAME
)

$OLD_GROUP=Get-ADGroup "$OLD_GROUP_NAME"

If ($OLD_GROUP -eq $null)
{
    "Cannot clone non-existent group ($OLD_GROUP_NAME)"
}
Else
{
    $OLD_GROUP_SCOPE=$OLD_GROUP.GroupScope
    $OLD_GROUP_DN=$OLD_GROUP.DistinguishedName
    $TEMP=$OLD_GROUP_DN.IndexOf(",")
    $OLD_GROUP_PATH=$OLD_GROUP_DN.SubString($TEMP+1,$OLD_GROUP_DN.Length-$TEMP-1)

    New-ADGroup -Name $NEW_GROUP_NAME -GroupScope $OLD_GROUP_SCOPE -path "$OLD_GROUP_PATH"
    Get-ADGroupMember -Identity $OLD_GROUP_NAME | Add-ADPrincipalGroupMembership -MemberOf $NEW_GROUP_NAME

    $NEW_GROUP=Get-ADGroup -Filter { name -like $NEW_GROUP_NAME }
    If ($NEW_GROUP -eq $null)
    {
        "Error creating group ($NEW_GROUP_NAME)"
    }
    Else
    {
        "Created new Group $NEW_GROUP_NAME (path $OLD_GROUP_PATH)"
    }
}

Powershell – Clone list of groups

Example usage

Create a file with the foilowing format:

OLD_GROUP_NAME1;CLONED_GROUP_NAME1
OLD_GROUP_NAME2;CLONED_GROUP_NAME2
...

And pass it as parameter of the script:

PS D:\SCRIPTS> .\Clone_Group_List.ps1 <GROUPS_FILE>

For example, file D:\TEMP\groups.txt

SG-Test1;SG-NewTest1
SG-Test2;SG-NewTest2
PS D:\SCRIPTS> .\Clone_Group_List.ps1 D:\TEMP\groups.txt
Created new Group SG-NewTest1 (path OU=MyGROUPS,DC=domain,DC=com)
Created new Group SG-NewTest2 (path OU=MyGROUPS,DC=domain,DC=com)

Code (Clone_Group_List.ps1)

Download the code of Clone_Group_List.ps1

Param(
  [string] $GROUPS_FILE
)

$GROUPS=Get-Content "$GROUPS_FILE"
ForEach ($LINE in $GROUPS)
{
    $OLD_GROUP_NAME=$LINE.Split(";")[0]
    $NEW_GROUP_NAME=$LINE.Split(";")[1]

    $OLD_GROUP=Get-ADGroup -Filter { name -like $OLD_GROUP_NAME }    

    If ($OLD_GROUP -eq $null)
    {
        "Cannot clone non-existent group ($OLD_GROUP_NAME)"
    }
    Else
    {
        $OLD_GROUP_SCOPE=$OLD_GROUP.GroupScope
        $OLD_GROUP_DN=$OLD_GROUP.DistinguishedName
        $TEMP=$OLD_GROUP_DN.IndexOf(",")
        $OLD_GROUP_PATH=$OLD_GROUP_DN.SubString($TEMP+1,$OLD_GROUP_DN.Length-$TEMP-1)

        New-ADGroup -Name $NEW_GROUP_NAME -GroupScope $OLD_GROUP_SCOPE -path "$OLD_GROUP_PATH"
        Get-ADGroupMember -Identity $OLD_GROUP_NAME | Add-ADPrincipalGroupMembership -MemberOf $NEW_GROUP_NAME
        $NEW_GROUP=Get-ADGroup -Filter { name -like $NEW_GROUP_NAME }
        If ($NEW_GROUP -eq $null)
        {
            "Error creating group ($NEW_GROUP_NAME)"
        }
        Else
        {
            "Created new Group $NEW_GROUP_NAME (path $OLD_GROUP_PATH)"
        }
    }
}