0 votes

I'm trying to combine these two scripts to effectively store a user's group memberships in customattributebinary5 and then be able to copy and paste those memberships to a new user in the future. So far I think I have everything except for the pasting of the groups to a new user as I'm having trouble converting the logic from groups to users.

Remove groups from user and store in attribute:

# $groupNamesToSkip = @("MyGroup1", "MyGroup2", "Department*") # TODO: modify me
$groupNamesToSkip = $null

function SkipGroup($patterns, $sAMAccountName)
{
    foreach ($pattern in $patterns)
    {
        if ($sAMAccountName -like $pattern)
        {
            return $True
        }
    }

    return $False
}

# Get all groups user is a direct member of
$groupGuids = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")

# Build a single-dimension array of member GUIDs
$totalBytes = $groupGuids.Count * 16
$result = New-Object 'System.Collections.Generic.List[System.Byte]' $totalBytes
foreach ($GuidBytes in $groupGuids)
{
    $result.AddRange($GuidBytes)
}
# Save the GUIDs to the adm-CustomAttributeBinary5 virtual property of target user
$Context.TargetObject.Put("adm-CustomAttributeBinary5", $result.ToArray())
$Context.TargetObject.SetInfo()

# Get the Primary Group ID
$primaryGroupId = $Context.TargetObject.Get("primaryGroupID")

foreach ($groupGuidBytes in $groupGuids)
{
    # Bind to the group
    $groupGuid = New-Object "System.Guid" (,$groupGuidBytes)
    $groupGuid = $groupGuid.ToString("B")
    $groupPath = "Adaxes://<GUID=$groupGuid>"
    $group = $Context.BindToObject($groupPath)

    # Skip Primary Group
    if ($group.Get("primaryGroupToken") -eq $primaryGroupId)
    {
        continue
    }

    # Skip special groups
    $sAMAccountName = $group.Get("sAMAccountName")
    if (($groupNamesToSkip -ne $NULL) -and 
        (SkipGroup $groupNamesToSkip $sAMAccountName))
    {
        continue
    }

    # Remove user from the group
    $group.Remove($Context.TargetObject.AdsPath)
}

Copy groups from user to initiator:

# Get an array of member GUIDs
try
{
    $sourceMemberGuids = $Context.TargetObject.Get("adm-CustomAttributeBinary5")
}
catch
{
    $Context.Cancel("Failed to get member GUIDs.")
    return
}

# Calculate the number of GUIDs
$totalBytes = $sourceMemberGuids.Length

# Make sure that the total number of bytes is a divisible of 16
$remainder = 0
[System.Math]::DivRem($totalBytes, 16, [ref] $remainder)
if ($remainder -ne 0)
{
    $Context.Cancel("Unexpected data length! Exiting.")
    return
}

# Save the GUIDs to the adm-CustomAttributeBinary1 virtual property user who invokes the script
$Context.Initiator.UserAdsObject.Put("adm-CustomAttributeBinary1", $sourceMemberGuids)
$Context.Initiator.UserAdsObject.SetInfo()


And finally, need help with pasting, as this doesn't work:

# Get the Primary Group ID
$primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
#change this to skip certain groups
$groupNamesToSkip = $null

# Get an array of member GUIDs
try
{
    $sourceMemberGuids = $Context.Initiator.UserAdsObject.Get("adm-CustomAttributeBinary1")
}
catch
{
    $Context.Cancel("Failed to get member GUIDs.")
    return
}

# Calculate the number of GUIDs
$totalBytes = $sourceMemberGuids.Length

# Make sure that the total number of bytes is a divisible of 16
$remainder = 0
[System.Math]::DivRem($totalBytes, 16, [ref] $remainder)
if ($remainder -ne 0)
{
    $Context.Cancel("Unexpected data length! Exiting.")
    return
}

foreach ($groupGuidBytes in $sourceMemberGuids)
{
    # Bind to the group
    $groupGuid = New-Object "System.Guid" (,$groupGuidBytes)
    $groupGuid = $groupGuid.ToString("B")
    $groupPath = "Adaxes://<GUID=$groupGuid>"
    $group = $Context.BindToObject($groupPath)
    $groupName = $group.Get("cn")

    # Skip the group if it is the user's Primary Group
    if (($group.Get("primaryGroupToken") -eq $primaryGroupId) -or ($groupNamesToSkip -contains $groupName))
    {
        continue
    }

    # Add user to the group
    $group.Add($Context.TargetObject.AdsPath)
    $Context.LogMessage("Added the user to group '$groupName'", "Information")
}
by (2.5k points)
0

Hello,

For us to help you with a solution, please, specify what version of Adaxes you are currently using. For information on how to check that, have a look at the following help article: https://www.adaxes.com/help/?HowDoI.ManageService.CheckAdaxesServiceVersion.html.

0

2019.1 Version 3.11.16825.0

0

Hello,

Thank you for clarifying. We suggest that you only use two scripts. The first one will be used to remove all group memberships of a user and save group GUIDs to a custom binary attribute. For example, it can be executed in a Custom Command. The second script will be executed using a Custom Command with an AD object picker parameter. The parameter will be used to specify the user account that has groups the target account should be added to in a custom binary attribute. If this approach meets your needs, we will provide you with the scripts.

0

Yes, that approach would be sufficent. In our case, the removal of all groups is a scheduled task that runs after a user has been disabled for more than 4 weeks and checks to see that customattributebinary5 is $null. Thanks.

1 Answer

+1 vote
by (189k points)

Hello,

Thank you for the confirmation. We updated the script for removing and preserving groups, find it below. In the script, the $binaryAttributeName variable specifies the LDAP name of the custom binary attribute (e.g. adm-CustomAttributeBinary5) that will be used to store group GUIDs.

$binaryAttributeName = "adm-CustomAttributeBinary5" # TODO: modify me

# Get all groups user is a direct member of
$groupGuidsBytes = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")

# Get the Primary Group ID
$primaryGroupId = $Context.TargetObject.Get("primaryGroupID")

# Build a single-dimension array of group GUIDs
$totalBytes = $groupGuidsBytes.Count * 16
$result = New-Object 'System.Collections.Generic.List[System.Byte]' $totalBytes

foreach ($guidBytes in $groupGuidsBytes)
{
    # Bind to the group
    $guid = [Guid]$guidBytes
    $group = $Context.BindToObject("Adaxes://<GUID=$guid>")

    # Skip Primary Group
    if ($group.Get("primaryGroupToken") -eq $primaryGroupId)
    {
        continue
    }

    # Add guid bytes to the array
    $result.AddRange($guidBytes)

    # Remove user from the group
    $group.Remove($Context.TargetObject.AdsPath)
}

if ($result.Count -ne 0)
{
    # Save the GUIDs to the custom attribute of target user
    $Context.TargetObject.Put($binaryAttributeName, $result.ToArray())
    $Context.TargetObject.SetInfo()
}

To create the Custom Command for adding users to groups:

  1. Launch Adaxes Administration Console.
  2. In the Console Tree, right-click your service node.
  3. In the context menu, navigate to New and click Custom Command. image.png
  4. On step 2 of the Create Custom Command wizard, select the User object type and click Next. image.png
  5. Click New.
  6. Select AD object picker and click Next.

image.png

  1. Specify a parameter name and display name (e.g. userTemplate and User to get groups from). image.png
  2. Click Next.
  3. Click Configure.
  4. In the Display only objects that match the following LDAP filter field, enter the following: (sAMAccountType=805306368) image.png
  5. Click OK and then click Finish.
  6. Click Next.
  7. Click Add an action.
  8. Select Run a program or PowerShell script.
  9. Paste the below script into the Script field. In the script:
    • $binaryAttributeName - Specifies the LDAP name of the custom binary attribute (e.g. adm-CustomAttributeBinary5) that will be used to get group GUIDs from the user selected in the parameter. The LDAP name Should the same as in the $binaryAttributeName variable of the first script.
    • $objectDN - Specifies the distinguished name (DN) of the user selected in the parameter. The DN is obtained using a value reference containing the name of the parameter with the param- prefix (e.g. param-userTemplate).
$binaryAttributeName = "adm-CustomAttributeBinary5" # TODO: modify me
$objectDN = "%param-userTemplate%" # TODO: modify me

# Get array of group GUIDs
$object = $Context.BindToObjectByDN($objectDN)
try
{
    $sourceGroupGuids = $object.Get($binaryAttributeName)
}
catch
{
    $Context.Cancel("Failed to get group GUIDs.")
    return
}

# Calculate the number of GUIDs
$totalBytes = $sourceGroupGuids.Length

# Make sure that the total number of bytes is divisible by 16
$remainder = 0
[System.Math]::DivRem($totalBytes, 16, [ref] $remainder)
if ($remainder -ne 0)
{
    $Context.Cancel("Unexpected data length!")
    return
}

$groupsToAdd = New-Object "System.Collections.Generic.HashSet[System.Guid]"
for ($i = 0; $i -lt ($totalBytes / 16); $i++)
{
    $bytes = [System.Guid]::Empty.ToByteArray()
    [System.Array]::Copy($sourceGroupGuids, $i * 16, $bytes, 0, 16)
    $guid = New-Object "System.Guid" (,$bytes)
    $groupsToAdd.Add($guid)
}

# Get GUIDs of groups the user is member of
$memberOfGuids = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")

# Adjust the list of groups to add the user to
foreach($memberOfGuidBytes in $memberOfGuids)
{
    $guid = New-Object "System.Guid" (,$memberOfGuidBytes)
    $groupsToAdd.Remove($guid) # Already a member of the group
}

# Add to groups
foreach($guid in $groupsToAdd)
{
    try
    {
        $group = $Context.BindToObject("Adaxes://<GUID=$guid>")
        $group.Add($Context.TargetObject.AdsPath)
    }
    catch
    {
        $Context.LogMessage("An error occurred when adding user %fullname% to the group. Error: " + $_.Exception.Message, "Warning")
    }
}
  1. Enter a short description and click OK. image.png
  2. Click Next and finish creating the Custom Command.

Related questions

0 votes
1 answer

With Active Directory Users and Computers, I can add group members by copying a list of usernames and pasting them into the Add Members dialog box. This is very quick and easy. How can I do this with Adaxes? It seems that I can only add one member at a time.

asked Feb 24, 2017 by abarker5 (480 points)
0 votes
1 answer

Hi, Group memberships are kept when using "User Copy" function. Is it possible to do the same thing between two existing users ? (custom commands or else) Thanks for your response, Yoann

asked Oct 4, 2012 by yoann.hamon (1.9k points)
0 votes
0 answers

We have users with group memberships in multiple domain. All groups are type Universal. For example we have DOMAIN A and child domains for each dept, such as ... group memberships during user account copy, including memberships from other domains? Thank you,

asked Sep 10 by maliguinem (250 points)
0 votes
1 answer

They can navigate to both the user or the group within the ADAXES web interface without issue. They can then either Add to Group or Add Member but the resulting ... something to the web interface which prevents changing the lookup domain. Any ideas? Thanks!

asked Apr 9 by VTPatsFan (3.7k points)
0 votes
1 answer

Our Help Desk currently 'mirrors' the group membership of a new user based on another existing user in our AD. I'd like to be able to automate this so that the initiator ... and 'paste' it on the new user being created. Any help on this would be appreciated!

asked Apr 21 by RayBilyk (690 points)
2,352 questions
2,106 answers
5,746 comments
126,669 users