The script allows you to execute custom commands when membership of an AD group changes, no matter whether the changes were made using Adaxes or any 3rd party tools, such as ADUC or Exchange.
To be able to identify which members were added to or removed from a group, the script saves GUIDs of the current members in a certain multi-valued attribute of the group. The saved GUIDs are used to compare the list of current members of the group with members on the previous run.
We suggest using an Adaxes custom attribute for storing member GUIDs, for example, adm-CustomAttributeTextMultiValue1. Such attributes are not stored in AD, but can be used the same as any other attribute of AD objects.
To use the script with Adaxes, create a scheduled task for Group objects that runs the script using the Run a program or PowerShell script action.
Parameters:
- $savedMembersAttribute - Specifies the LDAP display name of the attribute that will be used to store group member GUIDs.
- $customCommandIdAddedToGroup and $customCommandIdRemovedFromGroup - Specify the IDs of the Custom Commands that will be run on users who were added or removed from a group. How to get the ID of a Custom Command.
$savedMembersAttribute = "adm-CustomAttributeTextMultiValue1" # TODO: modify me
$customCommandIdAddedToGroup = "{D993945F-A9B7-4349-AE18-351F80D9DCD9}" # TODO: modify me
$customCommandIdRemovedFromGroup = "{9DB88EC3-1241-4AB1-9612-C7C982BAA49F}" # TODO: modify me
function SaveCurrentMembers($guidsBytes, $savedMembersAttribute)
{
if ($guidsBytes.Count -eq 0)
{
# All members were removed from the group
$Context.TargetObject.PutEx("ADS_PROPERTY_UPDATE", $savedMembersAttribute, @("none"))
}
else
{
$values = @()
foreach ($guidBytes in $guidsBytes)
{
$values += ([Guid]$guidBytes).ToString()
}
$Context.TargetObject.PutEx("ADS_PROPERTY_UPDATE", $savedMembersAttribute, $values)
}
# Save changes
$Context.TargetObject.SetInfo()
}
# Get GUIDs of direct members of the group
try
{
$currentMemberGuids = $Context.TargetObject.GetEx("adm-DirectMembersGuid")
}
catch
{
$currentMemberGuids = @()
}
$memberGuids = New-Object "System.Collections.Generic.HashSet[System.Guid]"
foreach ($guidBytes in $currentMemberGuids)
{
$guid = [Guid]$guidBytes
$memberGuids.Add($guid)
}
# Get saved member GUIDs
try
{
$savedMemberGuids = $Context.TargetObject.GetEx($savedMembersAttribute)
}
catch
{
if ($memberGuids.Count -eq 0)
{
return # No current and saved members
}
# Save current members GUIDs and exit
SaveCurrentMembers $currentMemberGuids $savedMembersAttribute
return
}
if (($savedMemberGuids.Length -eq 1) -and ($savedMemberGuids[0] -ieq "none"))
{
$savedMemberGuids = @() # All users were removed from the group previous time
}
# Find members that were removed from the group
$removedMemberGuids = @()
foreach ($savedMemberGuid in $savedMemberGuids)
{
$guid = [Guid]$savedMemberGuid
if ($memberGuids.Remove($guid))
{
continue
}
$removedMemberGuids += $guid
}
if (($removedMemberGuids.Length -eq 0) -and ($memberGuids.Count -eq 0))
{
return # No changes
}
if ($memberGuids.Count -ne 0)
{
# Execute Custom Command on members that were added
foreach ($newMemberGuid in $memberGuids)
{
# Bind to the member
$path = "Adaxes://<GUID=$newMemberGuid>"
$newMember = $Context.BindToObjectEx($path, $True)
# Execute the Custom Command
$newMember.ExecuteCustomCommand($customCommandIdAddedToGroup, $null)
}
}
if ($removedMemberGuids.Length -ne 0)
{
# Execute Custom Command on members that were removed
foreach ($removedMemberGuid in $removedMemberGuids)
{
# Bind to the member
$path = "Adaxes://<GUID=$removedMemberGuid>"
$removedMember = $Context.BindToObjectEx($path, $True)
# Execute the Custom Command for removed members
$removedMember.ExecuteCustomCommand($customCommandIdRemovedFromGroup, $null)
}
}
# Save current member GUIDs to custom attribute
SaveCurrentMembers $currentMemberGuids $savedMembersAttribute
Hello Tim,
Yes, it is possible to run the script in a Business Rule configured for the Group object type. However, to trigger the rule corresponding changes must be made to a group via Adaxes. For example, if the script will be executed in a Business Rule triggering After adding a member to a group, it will trigger only when a member is added to a group included into the rule Activity Scope via Adaxes. If a member is added via any other tool (e.g. ADUC), the rule will not trigger.