1

Issue: Take a list of usernames from a CSV file and recursively remove them from all of the user groups that they are a member of. I would like to limit what groups they are removed from based upon a prefix for the group name.

Example: If user_bob (one of the many usernames within the CSV) was a member of the the following groups (determined recursively): abc-users, abc-printers, abc-users-limited, xzy-users, xyz-secure, then I would like to have the PowerShell script remove him from all groups that are prefixed with "abc-" and then move on to the next username in the CSV and perform the same process.

Notes: I have been searching all over online for examples for something like this and cannot seem to locate any leads. Code snippets or samples that I can begin the process of testing with or putting together into a solution would be most appreciated. I have been looking through the TechNet documentation for the commandlets and have not made much progress. Thanks in advance!

John
  • 2,276
  • 7
  • 44
  • 60

2 Answers2

5

The base algorithm of what you're looking for looks something like this (according to me, anyway):

  1. Enumerate all of the group with the right prefix.
  2. Recursively follow their GroupMembers to enumerate any nested groups in them.
    1. Once you get a group with no groups as members, stop recursing.
  3. Take the list of users, for each user
    1. Enumerate their Group Memberships
    2. If any have the right prefix, remove them from it.
    3. If any of the remaining groups are in the list of groups enumerated in the previous major step, remove them from that one too.

Now for actual code-like things.

Enumerating all groups with a prefix (untested, there will be bugs):

$RecurseList=dsquery group -name "abc-*"
$TargetList=$RecurseList
foreach $Grp in $RecurseList {
    # Now get the members of that group, do not expand
    $GrpMembers=dsget group "$Grp" -members
    foreach ($Member in $GrpMembers) {
        $isGroup=dsget group $Member
        if ($isGroup.dn -eq $Member) {
            $TargetList.add("$Member")
            RecurseIntoGroup($isGroup.dn)
        }
    }
}

Then when it comes time to talk the CSV list, get the membership of the user, and check to see if that group exists in $TargetList above. If so, remove it.

This is a heck of a lot of work to go through when removing just one user from potentially thousands of groups, but if you're doing a LOT of these then having the pre-built list will save you time.

If you only need to do it for a few users (say, 10 or so), you can walk back up the tree.

$UserGroups = dsquery user -name $Username -memberof
foreach ($uGroup in $UserGroups) {
    if (isConcerning($uGroup)) {
        $ConcerningGroups.add("$uGroup")
    }
}

function isConcerning {
param ($uGroup)

$parentGroups=dsget group $uGroup -memberOf
$found=$False
foreach ($pg in $parentGroup) {
    if ($parentGroup.startswith("abc-")) {
    return($true)
    $found=$true
    } else {
        $concerning=isConcerning($pg)
        if ($concerning) {
            return($true)
            $found=$true
        } 
    }
}
if (-not $found) {
    return($False)
}

And then remove the concerning groups as needed.

sysadmin1138
  • 133,124
  • 18
  • 176
  • 300
5

Assuming that you what you want to do is remove EVERY user from all the groups with the particular prefix, not based on any other criteria (e.g. remove users abc from groups xyz, and users xyz from groups abc). Then you could do it like this. A couple of points first though:

  1. What format are the usernames in your CSV file? That will determine how you search for the user, you will need to update the parameter accordingly (eg. change $user.Identity to $user.SAMAccountName)
  2. This requires the AD Powershell cmdlets, so you either need to import the AD module first (or run it in the AD Powershell console on a DC or a computer with the admin tools installed)
  3. The following will only work for direct group membership, not recursive group membership.

$prefix = "CN=abc-*"

$userlist = Import-CSV userlist.csv

foreach ($user in $userlist) { $currentuser = Get-ADUser $user.Identity -properties memberof $grouplist = $currentuser.memberof

foreach ($group in $grouplist) { if ($group -like $prefix) { Get-ADGroup $group | Remove-ADGroupMember -members $currentuser -Confirm:$false } } }

If you need to search recursively you will need to try something else. you could have a look at item 11. in this post to see if it helps.

Matt
  • 1,893
  • 5
  • 28
  • 40