locked
Powershell find AD Groups that have only disabled users as members RRS feed

  • Question

  • I have been trying to find a way to list AD Groups that have only disabled users as members.  I have been asked to search domains and list the groups that have disabled users as members.  The various filters for Get-ADGroupMember piped to Get-ADUser don't seem enable this.  Thanks
    Friday, June 16, 2017 6:58 PM

Answers

  • My solution:

    # Retrieve distinguished names of all groups in the domain.
    $Groups = Get-ADGroup -Filter *
    
    "Groups with at least one disabled user and no enabled users:"
    # Note, the groups identified could still have group or computer object members.
    
    # Enumerate the groups.
    ForEach ($Group In $Groups)
    {
        $GroupDN = $Group.distinguishedName
        # Retrieve all enabled user members of the group.
        $Enabled = Get-ADUser -LDAPFilter "(&(memberOf=$GroupDN)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
        # Consider only groups with no enabled users.
        If (-Not $Enabled)
        {
            # Make sure there is at least one disabled member of the group.
            $Disabled = Get-ADUser -LDAPFilter "(&(memberOf=$GroupDN)(userAccountControl:1.2.840.113556.1.4.803:=2))"
            If ($Disabled) {$GroupDN}
        }
    }
    

    But the groups with only disabled users could still have computer or group members.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    • Marked as answer by fmdba1 Tuesday, June 20, 2017 2:33 PM
    Saturday, June 17, 2017 3:14 PM
  • The following works on a group and will tell you if any group member is enabled in the group.  It is the easiest way to tell if a goup has only disabled users.  If there are groups as members then you will have to check for that in a second step.

    if(get-adgroupmember testgrp2 | ?{$_.objectClass -eq 'user'}|Get-AdUSer|?{$_.Enabled}){
        #group has enabled users
    }else{
        # group has no enabled users
    }

    The issue of a user Primary has little to do with whether a use is in a group.  It will if you are looking at a user membership.  Then the primary group will not be displayed  since it cannot be removed.


    \_(ツ)_/

    • Marked as answer by fmdba1 Tuesday, June 20, 2017 2:33 PM
    Sunday, June 18, 2017 7:43 PM

All replies

  • Get-ADGroupMember GroupName | Foreach {
      if ((Get-ADUser $_).Enabled -eq $false) {
        $_
      }
    }


    If you find that my post has answered your question, please mark it as the answer. If you find my post to be helpful in anyway, please click vote as helpful. (99,108,97,121,109,97,110,50,64,110,121,99,97,112,46,114,114,46,99,111,109|%{[char]$_})-join''

    Friday, June 16, 2017 7:15 PM
  • Hi clayman2,  The query you supplied will show disabled users of a group I feed it.  I think my description was inadequate.  I need to search the domain for groups that only has disabled users as members and then output this list of groups to a file for later actions.  If the group has other groups as members, or members that are enabled then I want to not have them in the list.  I need to search through 4k plus groups in the smaller domain.  I don't know the groups and need to search which ones, if any meet the criteria. 
    • Edited by fmdba1 Friday, June 16, 2017 7:59 PM spelling
    Friday, June 16, 2017 7:55 PM
  • This is the script I have patched together:

    $groupname ='SomeGroup'
    Get-ADGroup -server SomeDomain -Identity:$groupName | Get-ADGroupMember | Foreach {
      if ((Get-ADUser $_).Enabled -eq $false) {
        $_
      }
    }

    Friday, June 16, 2017 8:02 PM
  • if(get-adgroupmember testgrp2 | ?{$_.objectClass -eq 'user'}|Get-AdUSer|?{$_.Enabled}){
        #group has enabled users
    }else{
        # group has no enabled users
    }


    \_(ツ)_/


    • Edited by jrv Friday, June 16, 2017 8:42 PM
    Friday, June 16, 2017 8:40 PM
  • My solution:

    # Retrieve distinguished names of all groups in the domain.
    $Groups = Get-ADGroup -Filter *
    
    "Groups with at least one disabled user and no enabled users:"
    # Note, the groups identified could still have group or computer object members.
    
    # Enumerate the groups.
    ForEach ($Group In $Groups)
    {
        $GroupDN = $Group.distinguishedName
        # Retrieve all enabled user members of the group.
        $Enabled = Get-ADUser -LDAPFilter "(&(memberOf=$GroupDN)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
        # Consider only groups with no enabled users.
        If (-Not $Enabled)
        {
            # Make sure there is at least one disabled member of the group.
            $Disabled = Get-ADUser -LDAPFilter "(&(memberOf=$GroupDN)(userAccountControl:1.2.840.113556.1.4.803:=2))"
            If ($Disabled) {$GroupDN}
        }
    }
    

    But the groups with only disabled users could still have computer or group members.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    • Marked as answer by fmdba1 Tuesday, June 20, 2017 2:33 PM
    Saturday, June 17, 2017 3:14 PM
  • I tried the query from richard and it did seem to process without errors, but I got no output.  I did find a group manually that has only disabled users as members so I know at least one exists in the domain.  My Powershell skills are not that developed, but I did think the If ($Disabled) {$GroupDN} would have wrote the groups to the console. I appreciate the help with this, and am sure others have run into this when doing AD housekeeping.   I am not sure how to implement jrv statement, so I haven't tried that.  I did try to put an out-file after the last bracket, but don't think it would matter if the console didn't list the groups.  
    Sunday, June 18, 2017 2:54 PM
  • I tested that line, where the script outputs $GroupDN if there are only disabled members, and it worked whether there was only one disabled member or several. If no groups have only disabled users, then the only output will be the string "Groups with at least one disabled user and no enabled users:".

    However, the script does not consider cases where users have the group designated as their "primary" group. The "primary" group should be "Domain Users", but it is possible to configure another "primary" for some users. Is it possible the disabled members have the group designated as their "primary"?

    Also, it occurred to me that the members could be contacts, which the script ignores. But a contact cannot be disabled.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Sunday, June 18, 2017 3:54 PM
  • I got no output at all.  I will verify tomorrow if the group that I know only has disabled users in it has been set as the primary group.   I did run into that issue the other day where LDAP failed to enumerate a member of a group that had that group set as the primary.  You could see all six members of the group in ADUC and Powershell, but LDAP returned only 5 members.  I don't have a lab set up just yet.  Yes, there are contacts in some of the various groups.  I did just remember that when I copied your script I used -

    $Groups = Get-ADGroup -Filter * -server domainname
    
    Now I am not sure that works.    Would it be better to output all the group names into a csv and then bring those back into the for each?

      
    Sunday, June 18, 2017 7:35 PM
  • The following works on a group and will tell you if any group member is enabled in the group.  It is the easiest way to tell if a goup has only disabled users.  If there are groups as members then you will have to check for that in a second step.

    if(get-adgroupmember testgrp2 | ?{$_.objectClass -eq 'user'}|Get-AdUSer|?{$_.Enabled}){
        #group has enabled users
    }else{
        # group has no enabled users
    }

    The issue of a user Primary has little to do with whether a use is in a group.  It will if you are looking at a user membership.  Then the primary group will not be displayed  since it cannot be removed.


    \_(ツ)_/

    • Marked as answer by fmdba1 Tuesday, June 20, 2017 2:33 PM
    Sunday, June 18, 2017 7:43 PM
  • The proposed from Richard did start displaying groups within the domain I am logged onto.  I checked and I did have a $GroupDN value from the child domain I am trying to query, when I add -server "Domainname" . It seems to stall in the ForEach at the first LDAP.  There is no error, it just immediately goes to prompt.  I have a group that has a single member and that member is disabled.  I was unable to get jrv script to work on that. Also I have been asked for another Powershell report to get description and managed by, primary group fields from a list of AD Groups, and include the nested groups.  That's another post I'm sure.
    Monday, June 19, 2017 3:31 PM
  • This script runs and is outputs two files, one with enabled users and one without.  I have two groups with very similar names, PC Team RO and PC Team RW.  Each has only one user with PC Team RO having the user as disabled.  The script correctly identified these.  More sorting will be required for groups with nested groups and groups with contact or computer objects, but this first pass greatly reduces that chore.  Between both proposals I have enough of a solution to work with.

    $Groups = Get-ADGroup -Filter 'GroupCategory -eq "Security"' -server "xyz"
    ForEach ($Group In $Groups)
    {$GroupDN = $Group.distinguishedName
    if(get-adgroupmember $GroupDN -server "xyz" | ?{$_.objectClass -eq 'user'}|Get-AdUSer -server "xyz"|?{$_.Enabled}){
        $GroupDN | Out-file "c:\users\$env:UserName\Documents\YesEnabledUsers.txt" –append 
    }else{
        $GroupDN | Out-file "c:\users\$env:UserName\Documents\NoEnabledUsers.txt" –append
        }}

    Tuesday, June 20, 2017 2:39 PM
  • This is the final way I was able to get the groups with disabled users as members. It worked on small and large domains. Your mileage may vary.

    #This script sorts security groups to find groups that contain only disabled users. Groups with nested groups, contacts and computers as members and groups without members are filtered out.
    #This script will not resolve groups that have members from other domains or foreign security principals.
    #Part 1 This part of script filters out any security groups with enabled users, leaving groups with disabled users and other group member objects like contacts, groups and computers.
    
    $Groups = Get-ADGroup -Filter 'GroupCategory -eq "Security"' -server "$Domain"
    ForEach ($Group In $Groups)
    {$GroupDN = $Group.distinguishedName
    if(get-adgroupmember $GroupDN -server "$Domain" | ?{$_.objectClass -eq 'user'}|Get-AdUSer -server "$Domain"|?{$_.Enabled}){
        $GroupDN | Out-file "c:\users\$env:UserName\Documents\GrpsWithEnabledUsers.txt" –append  
    }else{
        $GroupDN | Out-file "c:\users\$env:UserName\Documents\GrpsWithDisabledUsers.txt" –append
        }}
    
    
    #Part 2 This part of the script takes the previous output and filters for groups that contain at least 1 disabled user to eliminate null or empty groups. 
    
    $Groups = (Get-Content  c:\users\$env:UserName\Documents\GrpsWithDisabledUsers.txt)
    Foreach ($Group in $Groups) {Get-ADGroup -Identity "$Group" -Server "$Domain" 
    if(get-adgroupmember -Identity "$Group" -server "$Domain"| ?{$_.objectClass -eq 'user'}){ $Group |Out-file "c:\users\$env:UserName\Documents\GrpsWithDisabledUsers1.txt" –append
        
    }else{
        $Group | Out-file "c:\users\$env:UserName\Documents\GrpsWithoutDisabledUsers1.txt" –append
    }}
    
    
    #Part 3 This part takes the previous output of Part 2 and filters out groups that do not contain any users to eliminate groups with objects like contacts, groups, and computers.
    
    $Groups = (Get-Content  c:\users\$env:UserName\Documents\GrpsWithDisabledUsers1.txt)
    Foreach ($Group in $Groups) {Get-ADGroup -Identity "$Group" -Server "$Domain" 
    if(get-adgroupmember -Identity "$Group" -server "$Domain"| ?{$_.objectClass -ne 'user'}){ $Group |Out-file "c:\users\$env:UserName\Documents\GrpsWithoutDisabledUsers2.txt" –append
        
    }else{
        $Group | Out-file "c:\users\$env:UserName\Documents\GrpsWithDisabledUsers2.txt" –append
    }}
    
    
    
    #Part 4 This part is the final output and should have groups that have only contain disabled #users as members. The final output is a csv file. 
    
    
    $Domain= '$Domain'
    $Groups = ForEach ($Group in $(Get-Content c:\users\$env:UserName\Documents\GrpsWithDisabledUsers2.txt)) {Get-ADGroup -Identity "$Group" -Server "$Domain" -Properties Name, DistinguishedName, GroupCategory, GroupScope, whenCreated, whenChanged, member, memberOf, SamAccountName, Description |
        Select-Object Name, DistinguishedName, GroupCategory, GroupScope, whenCreated, whenChanged, SamAccountName, Description, 
            @{n='MemberCount';e={$_.member.count}}, 
            @{n='MemberOfCount';e={$_.memberOf.count}}, 
            @{n='DaysSinceChange';e={[math]::Round((New-TimeSpan $_.whenChanged).TotalDays,0)}},
            @{n='Domain';e={$Domain}} 
    }
    $Groups |Select-Object Name, SamAccountName, Description, DistinguishedName,
            GroupCategory, GroupScope, whenCreated, whenChanged, DaysSinceChange,
            MemberCount, MemberOfCount, Domain  |Export-Csv "c:\users\$env:UserName\Documents\GrpsWithDisabledUsers2.csv" -append -NotypeInformation
    

    Tuesday, July 11, 2017 7:17 PM