The base algorithm of what you're looking for looks something like this (according to me, anyway):
- Enumerate all of the group with the right prefix.
- Recursively follow their GroupMembers to enumerate any nested groups in them.
- Once you get a group with no groups as members, stop recursing.
- Take the list of users, for each user
- Enumerate their Group Memberships
- If any have the right prefix, remove them from it.
- 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.
I am using the following in my Disable user script (only added the part of removing the group membership)
$DisableIni = Read-host "Enter initials of the user you want to disable"
$DisableUser = Get-QADUser $DisableIni
# Check Groupmembership and populate the list to Notes
$groupmemberof=$DisableUser.memberof | Get-QADGroup
Foreach ($Group in $groupmemberof)
{$DisNotes = (get-qaduser $DisableIni).notes
Set-qaduser $DisableIni -notes "$DisNotes $Group;"}
# Remove all memberships from the user except for "Domain Users"
$DisableUser.memberOf | Get-QADGroup | where {$_.name -notmatch '^users|domain users$'} | Remove-QADGroupMember -member $DisableIni
why would i add the groups to notes you might ask, just in case i disabled the wrong user, it is always good to be able to undo ;)
Hope you find it usefull
Best Answer
The simplest way is to direct ADSI queries to the local WinNT provider - that will return local objects on the system you are interested in. These can be local or remote systems but this will attach to the local account and security objects rather than the AD.
With that you can then query and modify properties of the $user object.
To set the "Password Doesn't expire" Flag you need to set the relevant flag in the UserFlags attribute. You can find a useful table of these at Motobit here.
To forcibly set Joe's account password from the above example to never expire:
Modifying group memberships is a bit more involved but Microsoft's PowerShell Guy has a step by step walk though for adding Domain User accounts to a Local Group on a system which I think is exactly what you need.