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

Remove all group memberships for a user account

November 06, 2024 Views: 14142

The scripts remove a user from all groups including Microsoft Entra ones except for the primary group. To execute the scripts, create a business rule, custom command or scheduled task configured for the User object type.

Only remove from all groups

In the script, the $groupNamesToSkip variable specifies the groups from which the user should not be removed. If set to $Null the user for which the script is executed will be removed from all groups except for the primary one.

Edit Remove
PowerShell
$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)
{
    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
}

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

# Get the Primary Group ID
$primaryGroupId = $NULL
if ($Context.TargetObject.DirectoryType -eq 1)
{
    $primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
}

foreach ($guidBytes in $groupGuids)
{
    # Bind to the group
    $guid = [Guid]$guidBytes
    $group = $Context.BindToObject("Adaxes://<GUID=$guid>")
    
    # Skip special groups
    if ((SkipGroupByName $groupNamesToSkip $group) -or (SkipGroupByType $group $True $primaryGroupId))
    {
        continue
    }

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

Remove from all groups and send an email

This version of the script sends an email for each user with a list of groups the user has been removed from.

Parameters:

  • $to - Specifies a comma-separated list of recipients of the e-mail notifications. You can use value references to specify recipients. For example, if you use the %adm-ManagerEmail% template, the email will be sent to user managers.
  • $subject - Specifies the subject of the email notifications.
  • $reportHeader - Specifies template for the email notification header. In the emplate, the {0} placeholder will be replaced with a link to the user account in Adaxes Web interface.
  • $reportFooter - Specifies template for the email notification footer.
  • $groupNamesToSkip - Specifies groups from which the user should not be removed. If set to $NULL the user for which the script is executed will be removed from all groups except for the primary one.
You can use value references in the subject, header and footer.
Edit Remove
PowerShell
$groupNamesToSkip = @("Group1", "Group2", "Group3*") # TODO: modify me

# E-mail message settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "List of groups user '%name%' has been removed from" # TODO: modify me
$reportHeader = "<b>User {0} has been removed from the following groups:</b><br/>" # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # 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)
{
    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
}

# Get the default Web Interface address
$webInterfaceAddress = "%adm-WebInterfaceUrl%"
if ([System.String]::IsNullOrEmpty($webInterfaceAddress))
{
    $Context.LogMessage("Default web interface address not set for Adaxes service. For details, see http://www.adaxes.com/help/?HowDoI.ManageService.RegisterWebInterface.html", "Warning")
}

# Add link to user
$userGuid = [Guid]$Context.TargetObject.Get("objectGuid")
$reportHeader = [System.String]::Format($reportHeader, "<a href='$webInterfaceAddress`#/Browse/$userGuid'>%name%</a>")

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

# Get the Primary Group ID
$primaryGroupId = $NULL
if ($Context.TargetObject.DirectoryType -eq 1)
{
    $primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
}

$reportHeader += "<ol>"
$totalRemovedGroups = 0
foreach ($guidBytes in $groupGuids)
{
    # Bind to the group
    $guid = [Guid]$guidBytes
    $groupPath = "Adaxes://<GUID=$guid>"
    $group = $Context.BindToObject($groupPath)
    
    # Skip special groups
    if ((SkipGroupByName $groupNamesToSkip $group) -or (SkipGroupByType $group $True $primaryGroupId))
    {
        continue
    }

    # Remove user from the group
    $group.Remove($Context.TargetObject.AdsPath)
    $totalRemovedGroups++
    
    # Add group to the report
    $groupDisplayName = $Context.GetDisplayNameFromAdsPath($groupPath, $True)
    $reportHeader += "<li><a href='$webInterfaceAddress`#/Browse/$guid'>$groupDisplayName</a></li>"
}
$reportHeader += "</ol>"

# Build report
$htmlReport = $reportHeader + "<br/>Total remove groups:$totalRemovedGroups" + $reportFooter

# Send mail
$Context.SendMail($to, $subject, $NULL, $htmlReport)

Preserving the list of groups

Parameters:

  • $groupNamesToSkip - Specifies groups from which the user should not be removed. If set to $NULL the user for which the script is executed will be removed from all groups except for the primary one.
  • $filePath - Specifies the path to the file that will be created to preserve the groups.
You can use value references (e.g. %username%) as a part of the file path. Before the script is executed, the value references will be replaced with the property values of the user. For example, if you specify the following: \\server\share\%username%.txt, and run the script on a user whose username is jdoe, the resulting path will be \\server\share\jdoe.txt.
Edit Remove
PowerShell
$filePath = "\\server\share\%username%.txt" # 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)
{
    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
}

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

# Get the Primary Group ID
$primaryGroupId = $NULL
if ($Context.TargetObject.DirectoryType -eq 1)
{
    $primaryGroupId = $Context.TargetObject.Get("primaryGroupID")
}

# Create a plain text report
$report = New-Object "System.Text.StringBuilder"
$report.Append("The user was removed from the following groups:")
foreach ($guidBytes in $groupGuids)
{
    # Bind to the group
    $guid = [Guid]$guidBytes
    $groupPath = "Adaxes://<GUID=$guid>"
    $group = $Context.BindToObject($groupPath)
    
    # Skip special groups
    if ((SkipGroupByName $groupNamesToSkip $group) -or (SkipGroupByType $group $True $primaryGroupId))
    {
        continue
    }

    # Remove user from the group
    $group.Remove($Context.TargetObject.AdsPath)
    
    # Add the group to the report
    $report.AppendLine()
    $report.Append($group.Get("name"))
}

# Create a new text
$file = New-Item -Path $filePath -ItemType File

# Save the report to the file
Add-Content $file $report.ToString()
Comments 26
avatar
Sean Nicholas May 15, 2018
These group scripts work awesome as we do remove all groups and e-mail a csv files of the groups for future reference when doing a deprovision of a user. This comes in handy when the service desk has accidentally deprovisioned the wrong user on a rare occasion. I have a new flow that needs to be implemented and that is to remove all the groups except one, so they would have &quot;domain users&quot; and one additional group left. Do you know how to put that into the script?
avatar
Support May 21, 2018
We have updated the first two scripts according to your request. It is now possible to specify the groups that will be skipped.
avatar
Manuel Jul 03, 2020
Hi,
this script works great, but I do not see the action in the logs.
How can it be modified so that the user being removed from each group is logged in the Adaxes logs?
avatar
Support Jul 03, 2020

Hello Manuel,

To pass the remove from group operation through Adaxes pipeline (trigger Business Rules and create a log record), replace this line in the script

$group = $Context.BindToObject($groupPath)

with the following

$group = $Context.BindToObjectEx($groupPath, $True)

avatar
Quinn May 13, 2021
I have been testing the version of the script that sends the email of the list of groups removed. The script has been working despite the following warning. "The term '$groupNamesToSkip' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again." Also if I add the a group to be removed it fails to skip that group. The group is still removed.
avatar
Support May 13, 2021
Hello Quinn,

As per our check, the script works just fine. For troubleshooting purposes, please, provide the exact script you are using with all the modifications you made. If you do not want to post the script here, please, email it at support@adaxes.com.
avatar
Quinn May 13, 2021
Thanks for reply. Here's what I have.

$groupNamesToSkip = @("mmsd.licensing-m365-g3.users") # TODO: modify me

# E-mail message settings
$to = "%adm-InitiatorEmail%" # TODO: modify me
$subject = "List of groups user '%name%' has been removed from" # TODO: modify me
$reportHeader = "<b>User {0} has been removed from the following groups:</b><br/>" # TODO: modify me
$reportFooter = "<hr /><p><i>Please save information for future employee reference.</i></p>" # TODO: modify me

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

return $False
}

# Get the default Web Interface address
$webInterfaceAddress = "%adm-WebInterfaceUrl%"
if ([System.String]::IsNullOrEmpty($webInterfaceAddress))
{
$Context.LogMessage("Default web interface address not set for Adaxes service. For details, see http://www.adaxes.com/help/?HowDoI.ManageService.RegisterWebInterface.html", "Warning")
}

# Add link to user
$userGuid = [Guid]$Context.TargetObject.Get("objectGuid")
$reportHeader = [System.String]::Format($reportHeader, "<a href='$webInterfaceAddress`ViewObject.aspx?guid=$userGuid'>%name%</a>")

# Get all groups user is a direct member of
$groupGuidsBytes = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")
$totalRemovedGroups = $groupGuidsBytes.Length - 1
if ($totalRemovedGroups -eq 0)
{
$Context.LogMessage("This user is a member only the primary group", "Information")
return
}

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

$reportHeader += "<ol>"
foreach ($groupGuidBytes in $groupGuidsBytes)
{
# Bind to the group
$groupGuid = [Guid]$groupGuidBytes
$groupPath = "Adaxes://<GUID=$groupGuid>"
$group = $Context.BindToObject($groupPath)

# Skip the 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)

# Add group to the report
$groupDisplayName = [Softerra.Adaxes.Utils.ObjectNameHelper]::GetObjectName($groupPath, "IncludeParentPath")
$reportHeader += "<li><a href='$webInterfaceAddress`ViewObject.aspx?guid=$groupGuid'>$groupDisplayName</a></li>"
}
$reportHeader += "</ol>"

# Build report
$htmlReport = $reportHeader + "<br/>Total remove groups:$totalRemovedGroups" + $reportFooter

# Send mail
$Context.SendMail($to, $subject, $NULL, $htmlReport)
avatar
Support May 14, 2021
Hello Quinn,

Thank you for the provided script. We double-checked it and works just fine. Most probably, there is some unprintable character in your script that causes the issue. We recommend you to directly copy the script from this article (using the Copy button) into the script editor in Adaxes Administration console and modify the variables there.
avatar
Quinn May 14, 2021
Thanks again for the reply. I copied the script once again from above.. And still received the warning about $groupNamesToSkip. So then I searched and replaced all the "$" in the script with "$". Saved it and the script ran successfully.
avatar
Jack Apr 27, 2022
Receiving an error message for bot GetEx and Get. I assume Import-Module Adaxes is also needed in this script. I'm working off of the first example that simply removes the groups.

Exception calling "GetEx" with "1" argument(s): "The 'BCFB057DCCBF1C4D8E43CA06386E5AFB' property cannot be found in the cache." Stack trace: at <ScriptBlock>, <No file>: line 19
Exception calling "Get" with "1" argument(s): "The '513' property cannot be found in the cache." Stack trace: at <ScriptBlock>, <No file>: line 22
avatar
Support Apr 27, 2022
Hello Jack,

Import-Module Adaxes is not required here as no cmdlets are used.

Did you make any changes to the script? If so, please, provide the exact script you are using.
avatar
LEGIT Nov 30, 2022
I am working on the second script and get this error on line 71 that read: "Multiple ambigous overloads found for "GetObjectName" and the argument count: "2". Stack trace: at &lt;ScriptBlock, ; line 71
avatar
Support Dec 01, 2022
Hello,

The issue occurs because you are using Adaxes 2023. The old version of the scripts were not adapted for it. We updated all the three scripts accordingly. Please, clear browser cache, refresh the page and copy the script you need above.
avatar
LEGIT Dec 01, 2022
That worked. Thank you.
avatar
Eric Meisner Jul 19, 2023
We are using a handful of Adaxes rule based groups. Is there a way in PowerShell to check/exclude any rule based memberships from removal?
avatar
Support Jul 20, 2023
Hello Eric,

Sorry for the confusion, but we are not sure we understand what exactly you need to achieve. Membership in rule-based groups is only controlled by the specified rules. There is no possibility to override the rule in any way including PowerShell.
avatar
Terry Jul 21, 2023
We have users assigned to a MS Visio group in Azure. Is there a script that connects to Azure and removes the user from those types of groups? This group does not show up on-prem, only in the cloud.
avatar
Support Jul 21, 2023
Hello Terry,

If you are using Adaxes 2023 or later you can register your Azure AD domain in Adaxes. As a result, you will be able to natively manage all the Azure AD groups. As well, you will be able to use the script to remove users not only from on-premises AD groups, but also from cloud ones without adding any modifications.
avatar
Terry Jul 21, 2023
Yes, we have the latest Adaxes version however when we register our Azure AD domain, we go above our license limit due to the user accounts that we have in Azure. We cannot upgrade our user account license at this time (due to funding), any recommendations on how we can register Azure AD without violating our allowed number of accounts?
avatar
Support Jul 21, 2023
Hello Terry,

If you register an Azure AD domain and a synchronized on-premises AD domain in Adaxes, synchronized users will only be counted once towards the license limit. As such, to avoid the violation, you can, for example, add all the guest accounts to the unmanaged list. To do so, use the following script from our repository: https://www.adaxes.com/script-repository/add-guest-users-located-in-specific-organizational-units-to-unmanaged-accounts-s683.htm.
avatar
Cam Aug 31, 2023
I've set this up so the last script runs, reports the groups that will be removed, and then the first script runs and removes them.

The problem I see is that every time the script is run it goes through each account again and overwrites the output. So now I have a share full of text files that get overwritten with Domain Users since it's the only group not being removed.

Is there an elegant way to either skip the accounts that have already been cleaned or append the text files instead of overwriting them on subsequent script runs?
avatar
Support Sep 01, 2023
Hello Cam,

To achieve the desired, you can add the below code right after line $groupGuids = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid").
Edit Remove
PowerShell
if ($groupGuids.Length -eq 1)
{
    return
}
The condition will only be met by users that are members of only a primary group.
avatar
Daniel Sep 07, 2023
Any way to add shared mailboxes to this?
avatar
Support Sep 08, 2023
Hello Daniel,

Unfortunately, there is no such possibility.
avatar
Dustin Feb 07, 2024
I've been getting the following error since upgrading to Adaxes 2023.2:

"Multiple ambiguous overloads found for "GetObjectName" and the argument count: "2". Stack trace: at <ScriptBlock>, <No file>: line 71"

I've copied and pasted the new version shown above but I continue getting this error. When we get the email, it shows a numbered list with the number of groups the account was removed from, but every line is blank as far as the actual group names are concerned.

Any suggestions?
avatar
Support Feb 07, 2024
Hello Dustin,

The error is expected as the method was deprecated. As you can see, neither of the scripts in the article has the method. Just pick the one you need.
Leave a comment
Loading...

Got questions?

Support Questions & Answers