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 (540 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 (294k 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

How can I create a script that does these things For internal audit. objective Even removing all groups of a disconnected user, we will still know which groups the ... in the created group (audit)-sAMAccountName-access add the (user)-sAMAccountName in members

asked Jul 2, 2022 by alancardoso (40 points)
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 (80 points)
0 votes
1 answer

I am wanting to export a list of users including the properties of a specific custom attribute. Ideally, I would be able to run a get-admuser and filter on a custom attribute, but even an excel report with the custom attributes would work. Is this possible?

asked Sep 9, 2021 by ggallaway (300 points)
0 votes
1 answer

As part of offboarding a user I need to generate a report of all AD groups, Entra groups and all Azure / M365 roles and licenses the user has before they ... about keeping a record of the leavers configured profile to simplify cloning them onto new starters.

asked Jun 24 by dhardyuk (20 points)
0 votes
1 answer

I need to create a report of all enabled users in selected group or multiple groups. I am aware of the report named "Members of selected groups", but I don't know how to filter only enabled users. Is there a way to achieve this?

asked May 28 by gsoc.ssm (90 points)
3,588 questions
3,277 answers
8,303 comments
548,086 users