Check if the user is a member of a list of AD groups

79.1k views Asked by At
$groups = 'group1', 'group2'....

I need to check if the user is in a specific AD group and echo the group name if he is not ; can I do it in the pipeline?

I have googled a lot and cannot find anything, maybe I am too bad at Google search in English :).

$groups |
    Get-QADGroupMember |
    Get-QADUser -SamAccountName 'lalala' | ForEach-Object {
        if ($_.SamAccountName -ne $null) {
            Write-Host "ok"
        } else {
            Write-Host 'not ok'
        }
    }

How can I display: not ok. user is not ingroup_name?

4

There are 4 answers

0
G. Dawid On

Is @henrycarteruk answer truely the best way to acomplish that? Let's have an example: I have list of 50 groups and I want to check if user is a member of each group.

By this example:

  • I have to get list of members for each groups
  • I have to check if each list contains my user login
  • Write answer

Problems I see:

  • group can have many, many users
  • I can have many, many groups I want to check if user is member of

I did fast test:

  1. My user have 180 groups
  2. I want to check if he's member of 10 groups I took my ~20 seconds

My approche is below.

Have a list of groups you want to check, but you need whole DN of group.

$list = 'CN=Administrators,CN=Builtin,DC=Fabrikam,DC=com','CN=Administrators,CN=Builtin,DC=Fabrikam,DC=com','CN=Administrators,CN=Builtin,DC=Fabrikam,DC=com'

Get user groups:

$user_groups = (Get-ADUser $login -Properties memberof | Select-Object memberof).memberof

Check which groups user have:

foreach($group2 in $list){
        if($user_groups.Contains($group2)){
            Write-Host "$login is member of $group2"
        }else{
           Write-Host "$login is not a member of $group2"
        }
    }
3
henrycarteruk On

The question is why do you want to use the pipeline when just looping through the results is so easy?

To check if a user is a member of a list of groups:

$user = "TestUsername"
$groups = 'Domain Users', 'Domain Admins'

foreach ($group in $groups) {
    $members = Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty SamAccountName

    If ($members -contains $user) {
        Write-Host "$user is a member of $group"
    } Else {
        Write-Host "$user is not a member of $group"
    }
}

And for multiple users:

Seems this question gets a lot of views, so I've updated my answer to resolve the obvious problem of the original version. This isn't a model answer and isn't the most efficient, but it accomplishes the goal.

$users = "TestUsername1", "TestUsername2", "TestUsername3"
$groups = 'Domain Users', 'Domain Admins'

foreach ($group in $groups) {
    $members = Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty SamAccountName

    foreach ($user in $users) {
        If ($members -contains $user) {
            Write-Host "$user is a member of $group"
        } Else {
            Write-Host "$user is not a member of $group"
        }
    }
}
0
Santiago Squarzon On

The answers provided can work for the task at hand but are not giving the most effective method which is actually letting LDAP do its job instead of having PowerShell perform the filtering.

$groupsFilter = ''
# assuming we have the Group's SamAccountName
# create a filter clause for each group
'group1', 'group2', '...' | ForEach-Object {
   $groupsFilter += '(samAccountName={0})' -f $_
}

# We need the user's DistinguishedName
# to perform the Member Attribute filtering
$userDN = (Get-ADUser theUser).DistinguishedName

$filter = -join @(
   '(&'                          # AND, all conditions must be met
      '(!member={0})' -f $userDN # The user is NOT a member
      '(|'                       # OR, any of the conditions must be met
         $groupsFilter           # Follow with the filter for any of the groups
      ')'                        # Close OR clause
   ')'                           # Close AND clause
)

# Now with the constructed filter we can search for any group
# which's samAccountName is one of those in the array of Groups
# AND the target user IS NOT a Member of
Get-ADGroup -LDAPFilter $filter

If we are looking to find those groups where the user is not a recursive member, in the words, where the user is not a member of the group OR any nested group, we only need to change the (!member=...) clause to use a LDAP_MATCHING_RULE_IN_CHAIN:

'(!member:1.2.840.113556.1.4.1941:={0})' -f $userDN # The user is NOT a recursive member

To have a reference, the constructed LDAP Filter would look like this:

(&
   (!member=CN=someuser,OU=someOU,DC=someDomain)
   (|
      (samAccountName=group1)
      (samAccountName=group2)
      (samAccountName=group3)
   )
)
0
deadlydog On

If your server doesn't have the Active Directory PowerShell feature installed on it, you can use this method. Here I'm checking if a domain group is part of the local administrators group on the server, but you can just change the GroupPrincipal to UserPrincipal and supply the username if you want to check if a user belongs to a group. Also, if the group is a domain group, then use the $domainContext for both FindByIdentity calls.

function Test-DomainGroupIsMemberOfLocalAdministrators([string] $domainName, [string] $domainGroupName)
{
    Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement'
    $domainContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain, $domainName)
    $localMachineContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Machine)
    $domainGroup = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($domainContext, $domainGroupName)
    $localAdministratorsGroup = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($localMachineContext, "Administrators")

    if($domainGroup -ne $null)
    {
        if ($domainGroup.IsMemberOf($localAdministratorsGroup))
        {
            return $true
        }
    }
    return $false
}