Powershell command to compare AD user group memberships to a baseline - powershell

I'm trying to figure out the logic to do something like this:
Query all AD groups in a specific OU
Query all the users in a specific OU
Query all the user's group memberships
If any user belongs to one or more groups in the initial group query, output that information
If any user belongs to none of the groups in the initial group query, also output that information
I've dug around on this site and found a script that works for the most part, but I'm stuck on how I can compare the user's group membership to the original group query that I'm pulling. It looks like I could use the compare-object cmdlet but the parameters don't seem to include anything that would let me keep track of how many groups the two objects have in common.
The code I found online is below:
$groups = Get-ADGroup -Filter * | where {$_.distinguishedname -like "*,OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv"}
$users = Get-ADUser -Filter * | where {$_.distinguishedname -like "*,OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv"}
foreach ( $User in $Users ) {
$userGroups = Get-ADPrincipalGroupMembership $User
if ( $userGroups.Count -gt 1 ) {
"{0} is a member of the following {1} groups:" -f $User.SamAccountName, $userGroups.Count
foreach ( $group in $userGroups ) {
"`t{0}" -f $group.Name
}
} elseif ( $userGroups.Count -lt 1 ) {
"{0} is a member of the following {1} groups:" -f $User.SamAccountName, $userGroups.Count
foreach ( $group in $userGroups ) {
"`t{0}" -f $group.Name
}
}
}
The problem with this is that I don't have a way of comparing the user group names to the names of the group query in line 1. I also can't determine that a user belongs to 1 or more groups from that list. I'm not sure if I can use the same count method.

You can validate that accounts are member of at least one group from your reference list by using Compare-Object:
foreach ( $User in $Users ) {
$userGroups = Get-ADPrincipalGroupMembership $User
if (!(Compare-Object $userGroups $groups -IncludeEqual -ExcludeDifferent)) {
"{0} doesn't belong to any reference group." -f $User.SamAccountName
}
}
Side note: use the -SearchBase parameter instead of filtering the results of Get-ADUser and Get-ADGroup by a wildcard match on the distinguished name:
$groups = Get-ADGroup -Filter * -SearchBase 'OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv' -SearchScope Subtree
$users = Get-ADUser -Filter * -SearchBase 'OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv' -SearchScope Subtree

I ended up doing the following and it works well for what I need. In case anyone is interested, sample code is below:
#gets a list of all groups in a given OU and stores the objects in the $groups variable
$groups = Get-ADGroup -Filter * -SearchBase 'OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv' -Properties name | select name
#pipe each group object into a foreach loop and output a string value of the same group name and stores it into the $groups_string variable
$groups_string = $groups | % {$_.name}
#gets a list of all users in a given OU and stores the objects in the $users variable
$users = Get-ADUser -Filter * -SearchBase 'OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv'
$results=#{
"Username" = ""
"Groupname" = ""
}
$table=#()
#iterates through every user in the $users variable and retrieves their group memberships
foreach ($user in $users) {
#selects each group name and stores it in the $groupMembership variable
$groupMembership = Get-ADPrincipalGroupMembership $user | select name
#compares the names of each user's group to the baseline group name.
$groupMembership | foreach ($_) {
#If there is a match add the group name and the username to the $results hash table
if ($groups_string -contains $_.name) {
$results."Groupname" = $_.name
$results."Username" = $user.Name
#create a new PS object and supply the properties of the $results hash table to each object
$objresults = New-Object psobject -Property $results
#add each object to the $table array
$table += $objresults
}
}
}
#display/output the $table array and format it to fit
$table | ft -AutoSize

Related

How to get all groups that a user is a member of, based on group extensionattribute

I'm tryng to get all the groups the users of a domain are member of, but filtering only the groups with a given extensionattribute.
I set the extensionattribute12 of all the domain groups to better filter some queries (i.e. Infrastructure - security - elearning). My query should get only the user(s) groups with
extensionattribute12=security
(for example).
I use something like:
get-aduser -filter -Properties memberof | select name, #{ l="GroupMembership"; e={$_.memberof -join ";" } }
and I get all the groups of the users. How can I filter by group extensionattribute?
You could use the inverse relationship (member on the group object) to query all the groups a user is a member of, just 1 query per user. Here using an LDAP filter:
$groupLabel = "Security"
Get-ADUser -Filter * |ForEach-Object {
$groups = Get-ADGroup -LDAPFilter "(&(extensionattribute12=$groupLabel)(member=$($_.DistinguishedName)))"
[pscustomobject]#{
User = $_.SamAccountName
GroupMembership = $groups.DistinguishedName -join ';'
}
}
If you have to process a large number of users or group memberships, you may find it faster to retrieve all the groups satisfying the extensionAttribute12 criteria up front and use that list to filter the memberOf attribute on the users:
$groupLabel = "Security"
# Create a hash set and populate it with the distinguished
# names of all the groups we're looking for
$groupDNs = [System.Collections.Generic.HashSet[string]]::new(#(
Get-ADGroup -Filter "extensionAttribute12 -eq '$groupLabel'" |Select -Expand DistinguishedName
))
Get-ADUser -Filter * -Properties memberOf |ForEach-Object {
# Retrieve memberOf values and filter against the hash set
$groups = $_.memberOf |Where-Object { $groupDNs.Contains($_) }
[pscustomobject]#{
User = $_.SamAccountName
GroupMembership = $groups -join ';'
}
}
Make it with N+1 queries
$groups = #( Get-ADGroup -Filter '(extensionattribute12 -eq "security")' )
$users = #( $groups |
ForEach-Object { Get-ADGroupMember -Identity $_ -Recursive } |
Sort-Object -Unique )
$users # All users of all groups that have EA12 = security
Get-ADUser -filter {...} -Properties memberof | select name, #{ l="GroupMembership"; e={( $_.memberof | Get-ADGroup |?{ $_.extensionattribute12 -eq 'security' }) -join ";" }} |?{ $_.GroupMembership }

Powershell - Get User information from AD list

I'm a beginner in programming in general..
What I'm trying to do is to create a powershell script that will:
Get information on each user on an Active Directory group.
Inside each group there may be another group, so I would want it to get the list of users from each nested group as well.
Only give me the information for each group once.
This is what I have so far:
$list = Get-ADGroupMember Admins
foreach($u in $list) {
Get-ADObject $u
}
foreach ($_ in $u) {
if ($u.ObjectClass -eq 'user') {
Get-ADUser $u -Properties * | select givenname, surname, samaccountname | ft -autosize
} else {
Get-ADGroupMember $u -Recursive | select name, samaccountname | ft -autosize
}
}
So far I'm trying to get it to work with that one group 'Admins' and then if it does I would want to run the code for more groups at the same time.
Any help or guidance would be appreciated.
You seem to want only properties that are returned by default by Get-ADUser aswell as Get-ADGroup, so in both cases, there is no need to specify the -Properties parameter.
Get-ADGroupMember can return user, computer and group objects, so at the moment, your else condition expects groups, where you could end up with a computer object..
In your code, you output to console with ft -autosize both in the if and the else, but it would be simpler to capture both types of resulting objects in a variable at the start of the loop and output it as a whole afterwards:
# you can load a list of group names from a predefined array:
$Groups = 'Admins', 'Users'
# or load from a file, each group name listed on a separate line:
# $Groups = Get-Content -Path 'D:\Test\ADGroups.txt'
# or get all AD groups in the domain:
# $Groups = (Get-ADGroup -Filter *).Name
$result = foreach ($group in $Groups) {
Get-ADGroup -Filter "Name -eq '$group'" | ForEach-Object {
# we could use the $group variable, but this ensures correct casing
$groupName = $_.Name
$members = $_ | Get-ADGroupMember -Recursive
foreach ($member in $members) {
if ($member.objectClass -eq 'user') {
Get-ADUser -Identity $member.DistinguishedName |
Select-Object #{Name="GroupName"; Expression={$groupName}},
#{Name="MemberType";Expression={'User'}},
Name,
GivenName,
Surname,
SamAccountName
}
elseif ($member.objectClass -eq 'group') {
Get-ADGroup -Identity $member.DistinguishedName |
Select-Object #{Name="GroupName";Expression={$groupName}},
#{Name="MemberType";Expression={'Group'}},
Name,
#{Name="GivenName";Expression={''}}, # groups don't have this property
#{Name="Surname";Expression={''}}, # groups don't have this property
SamAccountName
}
}
}
}
# output is console
$result | Format-Table -AutoSize
# write to CSV file
$result | Export-Csv -Path 'D:\Test\GroupsInfo.csv' -NoTypeInformation
The trick is here to output objects with equal properties for both a user and a group object

Loop through nested AD groups until all members are found

I need help figuring out the logic for looping through Active Directory security groups to find all members of any nested groups using Get-ADGroupMember. If I use the recursive switch on that cmdlet, it doesn't capture the name of the nested group, just the members. I need to capture everything. I feel like this needs to be done using a while or do/while.
This section of code gets me most of the way there. However, I can't figure out how to prevent it from running the Get-AdGroupMember inside of the while if the objectclass is User. I'm testing with 4 AD groups called "testgroup1", "testgroup2", "testgroup3" and "testgroup4". Testgropus 1,2 and 3 each have a single user as a member. Testgroup2 is a member of Testgroup1. Testgroup3 is a member of Testgroup2. Testgroup4 is a member of Testgroup 3 and it also has 4 users as members.
$groups = Get-ADGroupMember 'testgroup1'
$allGroups =$null
While($groups){
$allGroups += $groups.SamAccountName
$groups = $groups.SamAccountName | Get-ADGroupMember
}
$allGroups
We solved this issue by creating a function that gets the members of an AD group and adds only users to an array. If the object class returns as a group it calls the same function again on that new group and then adds users under it to the same array. Code is below.
function Get-MBusers {
Param (
$Group,
$adserver
)
$users=#()
$members = Get-Adgroup -Identity $Group -Server $adserver -Properties members | Select-Object -ExpandProperty Members | Where-Object {$_ -notmatch "ForeignSecurityPrincipals"} | ForEach-Object {Get-ADObject $_ -Server $adserver}
foreach ($member in $members) {
Write-Debug "$($member.Name)"
$type = Get-ADObject $member -server $ADServer -Properties samAccountname
if ($type.ObjectClass -eq 'user') {
$users += Get-Aduser $type.samaccountname -Server $ADServer
}
# If it's a group
if ($type.ObjectClass -eq 'group') {
Write-Debug "Breaking out group $($type.Name)"
$users += Get-MBUsers $member $adserver
}
}
return $users
}

Filtering the AD group

I used the below code for pulling out AD group of users
$users = Get-Content u:\users.txt
ForEach ($User in $users) {
$user1 = Get-ADUser -Identity $User -Properties *;
$GroupMembership = ($user1.memberof | % { (Get-ADGroup $_).Name; }) -join ';';
$User1.SamAccountName + ';' + $GroupMembership >>test4.csv
}
I would like to add a filter which fetches the only particular type of ad group say starting with SG
I had tried putting a filter but it gave me a boolean true or false but not the filtered value.
You want to filter the Name property starting with SG?, try this:
Get-ADGroup -filter 'Name -like "SG*"'

pull only user name and select groups from AD with Power shell

I want to get all the users in my OU and list only the names of the users that are a member of any group with the word managers in it and list that group or groups they belong to.
So for example
TSmith
Equipment managers
Managers night shift
Bkline
Equipment managers Day Shift
I have been trying to tweak the below script.
The issue is if the user is a member of any group with managers in the name it list everything about that user. All the groups the last log on time everything in AD.
Thanks so much for any help.
Import-Module ActiveDirectory
$users = Get-ADUser -searchbase "OU=East,DC=CHM,DC=com" -Filter * -Properties *
foreach ( $user in $users ) {
$user
$groups = $user | select -ExpandProperty memberof
if ($groups -match 'manager') {
$user.samaccountname
$groups
}
}
Try this:
Get-ADUser -SearchBase "OU=East,DC=CHM,DC=com" -Search -ResultSetSize $null -Filter * -Properties memberOf | Foreach-Object {
# extract grouop names and check if they contain the word 'manager'
$manager = ($_.memberof -replace '^CN=([^,]+),.+$','$1') -like "*manager*"
if($manager)
{
New-Object -TypeName PSObject -Property #{
UserName = $_.SamAccountName
ManagerGroups = $manager -join ';'
}
}
}