We use cookies to improve your experience.
By your continued use of this site you accept such use.
For more details please see our privacy policy and cookies policy.

Script repository

Copy group membership from specified user

July 26, 2024 Views: 2313

The scripts copy group membership from the user specified to the target user.

Using a custom command parameter

The script copies group membership from the user specified in an AD object picker parameter of a custom command to the target user.

Parameters:

  • $sourceUserDNParamName - Specifies the name of the parameter used to select the source user with the param- prefix.
  • $replaceGroups - If set to $True, the script will replace all the target user group membership with that of the source user. If set to $False, the target user will retain its group membership and will be added to the groups the source user is a member of.
  • $onlyEntraGroups - If set to $True, the script will only add the target user to the Microsoft Entra groups the source user is a member of. If set to $False, the target user will be added to all the groups the source user is a member of.
  • $groupNamesToSkip - Specifies sAMAccountNames of the groups that should be skipped by the script.
Edit Remove
PowerShell
$sourceUserDNParamName = "param-User" # TODO: modify me
$replaceGroups = $False # TODO: modify me
$onlyEntraGroups = $False # TODO: modify me
$groupNamesToSkip = @("Group1", "Group2", "Group3*") # TODO: modify me

function SkipGroupByName($patterns, $group)
{
    if ($NULL -eq $patterns)
    {
        return $False
    }
    
    if ($group.DirectoryType -eq 1)
    {
        $groupName = $group.Get("sAMAccountName")
    }
    else
    {
        $groupName = $group.Get("name")
    }
    
    foreach ($pattern in $patterns)
    {
        if ($groupName -like $pattern)
        {
            return $True
        }
    }
    
    return $False
}

function SkipGroupByType($group, $skipPrimaryGroup, $primaryGroupId, $onlyEntraGroups)
{
    if ($onlyEntraGroups -and $group.DirectoryType -ne 2)
    {
        continue
    }
    
    if (($group.DirectoryType -eq 1) -and $skipPrimaryGroup)
    {
        # Check if the group is primary
        if ($group.Get("primaryGroupToken") -eq $primaryGroupId)
        {
            return $True
        }
    }

    # Check if the group is dynamic
    try
    {
        $dynamicMembership = $group.Get("adm-AzureDynamicMembership")
    }
    catch
    {
        $dynamicMembership = $False
    }
    
    # Check if the group is Rule based
    $isRuleBasedGroup = $group.MembershipType -eq "ADM_GROUPMEMBERSHIPTYPE_RULEBASED"
    
    return $dynamicMembership -or $isRuleBasedGroup
}

# Bind to the source user
$sourceUserDN = $Context.GetParameterValue($sourceUserDNParamName)
$sourceUser = $Context.BindToObjectByDN($sourceUserDN)

# Get groups to add
$groupGuidsToAdd = New-Object "System.Collections.Generic.HashSet[System.Guid]"
$sourceUser.GetEx("adm-DirectMemberOfGuid") | %%{[void]$groupGuidsToAdd.Add([Guid]$_)}

# Get current groups
$currentGroupGuids = New-Object "System.Collections.Generic.HashSet[System.Guid]"
$Context.TargetObject.GetEx("adm-DirectMemberOfGuid") | %%{[void]$currentGroupGuids.Add([Guid]$_)}

# Update groups
foreach ($guidBytes in $groupGuidsToAdd)
{
    $guid = [Guid]$guidBytes
    if ($currentGroupGuids.Remove($guid))
    {
        continue
    }
    
    # Skip special groups
    $group = $Context.BindToObjectEx("Adaxes://<GUID=$guid>", $True)
    if ((SkipGroupByName $groupNamesToSkip $group) -or (SkipGroupByType $group $False $NULL $onlyEntraGroups))
    {
        continue
    }

    $group.Add($Context.TargetObject.AdsPath)
}

if ($replaceGroups)
{
    $primaryGroupId = $NULL
    if ($Context.TargetObject.DirectoryType -eq 1)
    {
        # Get the primary group ID
        $primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
    }
    
    foreach ($guidBytes in $currentGroupGuids)
    {
        $guid = [Guid]$guidBytes
        $group = $Context.BindToObjectEx("Adaxes://<GUID=$guid>", $True)

        # Skip the group if it is the user's Primary Group
        if (SkipGroupByType $group $True $primaryGroupId $onlyEntraGroups)
        {
            continue
        }
        
        $group.Remove($Context.TargetObject.AdsPath)
    }
}

Using a DN syntax property

The script copies group membership from the user specified in a DN syntax property (e.g. Assistant) of the target user.

Parameters:

  • $sourceUserDNPropertyName - Specifies the LDAP name of the DN syntax property storing the user to copy membership from.
  • $replaceGroups - If set to $True, the script will replace all the target user group membership with that of the source user. If set to $False, the target user will retain its group membership and will be added to the groups the source user is a member of.
  • $onlyEntraGroups - If set to $True, the script will only add the target user to the Microsoft Entra groups the source user is a member of. If set to $False, the target user will be added to all the groups the source user is a member of.
  • $groupNamesToSkip - Specifies sAMAccountNames of the groups that should be skipped by the script.
Edit Remove
PowerShell
$sourceUserDNPropertyName = "assistant" # TODO: modify me
$replaceGroups = $False # TODO: modify me
$onlyEntraGroups = $False # TODO: modify me
$groupNamesToSkip = @("Group1", "Group2", "Group3*") # TODO: modify me

function SkipGroupByName($patterns, $group)
{
    if ($NULL -eq $patterns)
    {
        return $False
    }
    
    if ($group.DirectoryType -eq 1)
    {
        $groupName = $group.Get("sAMAccountName")
    }
    else
    {
        $groupName = $group.Get("name")
    }
    
    foreach ($pattern in $patterns)
    {
        if ($groupName -like $pattern)
        {
            return $True
        }
    }
    
    return $False
}

function SkipGroupByType($group, $skipPrimaryGroup, $primaryGroupId, $onlyEntraGroups)
{
    if ($onlyEntraGroups -and $group.DirectoryType -ne 2)
    {
        continue
    }
    
    if (($group.DirectoryType -eq 1) -and $skipPrimaryGroup)
    {
        # Check if the group is primary
        if ($group.Get("primaryGroupToken") -eq $primaryGroupId)
        {
            return $True
        }
    }

    # Check if the group is dynamic
    try
    {
        $dynamicMembership = $group.Get("adm-AzureDynamicMembership")
    }
    catch
    {
        $dynamicMembership = $False
    }
    
    # Check if the group is Rule based
    $isRuleBasedGroup = $group.MembershipType -eq "ADM_GROUPMEMBERSHIPTYPE_RULEBASED"
    
    return $dynamicMembership -or $isRuleBasedGroup
}

# Bind to the source user
$sourceUserDN = $Context.TargetObject.Get($sourceUserDNPropertyName)
$sourceUser = $Context.BindToObjectByDN($sourceUserDN)

# Get groups to add
$groupGuidsToAdd = New-Object "System.Collections.Generic.HashSet[System.Guid]"
$sourceUser.GetEx("adm-DirectMemberOfGuid") | %%{[void]$groupGuidsToAdd.Add([Guid]$_)}

# Get current groups
$currentGroupGuids = New-Object "System.Collections.Generic.HashSet[System.Guid]"
$Context.TargetObject.GetEx("adm-DirectMemberOfGuid") | %%{[void]$currentGroupGuids.Add([Guid]$_)}

# Update groups
foreach ($guidBytes in $groupGuidsToAdd)
{
    $guid = [Guid]$guidBytes
    if ($currentGroupGuids.Remove($guid))
    {
        continue
    }
    
    # Skip special groups
    $group = $Context.BindToObjectEx("Adaxes://<GUID=$guid>", $True)
    if ((SkipGroupByName $groupNamesToSkip $group) -or (SkipGroupByType $group $False $NULL $onlyEntraGroups))
    {
        continue
    }

    $group.Add($Context.TargetObject.AdsPath)
}

if ($replaceGroups)
{
    $primaryGroupId = $NULL
    if ($Context.TargetObject.DirectoryType -eq 1)
    {
        # Get the primary group ID
        $primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
    }
    
    foreach ($guidBytes in $currentGroupGuids)
    {
        $guid = [Guid]$guidBytes
        $group = $Context.BindToObjectEx("Adaxes://<GUID=$guid>", $True)

        # Skip the group if it is the user's Primary Group
        if (SkipGroupByType $group $True $primaryGroupId $onlyEntraGroups)
        {
            continue
        }
        
        $group.Remove($Context.TargetObject.AdsPath)
    }
}
Comments 3
avatar
Dave Jan 31, 2023
We've been using a version of this script for a while in a custom command to copy groups between users. When a group is configured with dynamic membership members cannot be manually added to the group. We've started having issues with errors that occur when a group that is in the list is configured with dynamic membership in Adaxes. I was wondering how we would modify the script to skip groups that user membership rules.
avatar
Support Jan 31, 2023
Hello Dave,

Please, specify which of the two scripts you need updated.
avatar
Frederik Jul 26, 2024
I have the same issue as Dave.

We use the "Using a custom command parameter" version of the script.

Copying group membership goes well, but we get a lot of errors due the script trying to add or remove the user to or from dynamic user groups.

The log shows:
Add [user] to [groupname] ([domainname].onmicrosoft.com\Groups)
Insufficient privileges to complete the operation.

I would like to be able to exclude dynamic user groups from the script. Unfortunately our naming have not been the best, so doing it on name will not work. I would like to exclude on a group property.
avatar
Support Jul 26, 2024
Hello Frederik,

Such a thing can happen in case a group is dynamic in Microsoft Entra or rule-based in Adaxes. We updated the scripts to skip such groups.
Leave a comment
Loading...

Got questions?

Support Questions & Answers