Tag Archives: powershell

Flatten nested AD group memberships with powershell

Several applications at my job do not know how to read nested security groups. This is annoying because we grant everything through security groups instead of individual entitlements.

I’ve recently finished writing a powershell script that will “flatten” a security group that has nested security groups. This script reads a security group’s membership, compares the individually assigned users with the nested security group membership, and then reconciles them so only members of the nested security group are individually added to the main group. It allows me to simply add a security group to another security group, and still be able to use the group to grant access to applications that don’t support nested groups. It also ensures that nobody has rogue access they shouldn’t have. Everything managed through groups like God intended.

I consulted a ton of different sites to accomplish this. Here are just a few:

https://www.reddit.com/r/PowerShell/comments/3f7iki/flatten_out_active_directory_groups_containing/

https://stackoverflow.com/questions/11526285/how-to-count-objects-in-powershell

https://stackoverflow.com/questions/41658770/determining-object-type

https://docs.microsoft.com/en-us/powershell/module/activedirectory/

https://ss64.com/ps/syntax-compare.htmlhttps://ss64.com/ps/compare-object.html

#Nested Security Group flattener script
#Written by Nicholas Jeppson, 10/6/2018

#This script scans nested security groups and compares their membership to that of the base security group.
#It then reconciles membership so that the only members of this group are those who are members of the nested security groups.
#This is required for applications that cannot read nested security groups, such as mattermost.
#No more manually adding people to a group after you've already added their role to that same group!

#=============Variables section=============#

#Enter groups to reconcile here, separated by quotes and a comma:
$groups_to_flatten = @("group1","group2")

#==========End Variables Section=============#

#Loop through each group to flatten
foreach ($group in $groups_to_flatten) {

    Write-Host "`nProcessing group ""$group"""

    #Read current individually added users
    $individually_added_users = get-ADGroupMember -Identity $group | Where-Object {$_.objectClass -eq 'user'}

    #Read group membership of nested groups - Ignore specific user (optional)
    $nested_group_members = get-ADGroupMember -Identity $group | Where-Object {$_.objectClass -eq 'group'} | Get-ADGroupMember -Recursive | Where-Object {$_.name -ne 'USER_TO_IGNORE'}

    #Compare current individually added users with that of nested security groups
    $users_to_add = Compare-Object -ReferenceObject $individually_added_users -DifferenceObject $nested_group_members -PassThru | Where-Object {$_.SideIndicator -eq "=>"}
    $users_to_remove = Compare-Object -ReferenceObject $individually_added_users -DifferenceObject $nested_group_members -PassThru | Where-Object {$_.SideIndicator -eq "<="}
    
    #loop through each user to remove and remove them
    foreach ($user in $users_to_remove) {
        Remove-ADGroupMember -Identity $group -Member $user -Confirm:$false
        Write-Host "Removed: $user"
    }
    
    #loop through each user to add and add them
    foreach ($user in $users_to_add) {
        #Add nested group membership individually back to the parent group
        #Write-Host "Adding individual members to ""$group""`n`n"
        Add-ADGroupMember -Identity $group -Members $user -Confirm:$false 
        Write-Host "Added: $user"   
    }
}

Powershell equivalent of “find -exec”

I recently found myself on a Windows 10 system needing to do the equivalent of “find . -name *.mdi -exec mdiconvert -source {} -log log.txt \;” I knew what to do instantly on a Unix system, not so on a Windows system

I finally figured it out and am now writing it down because I know I’ll forget! Thanks to these several sites for pointing me in the right direction.

  • Get-ChildItem is the find equivalent
    • -Filter is the -name equivalent
    • -Recurse must be specified otherwise it only looks in the one directory
  • % is an alias for “ForEach-Object
  • Put the command you want run in brackets {}
  • Put an ampersand in front of the command you wish to run so you can properly pass arguments containing dashes
  • $_.FullName turns the powershell object into a text string (which my command required.) FullName is the full path of the item found with Get-ChildItem
    • $_ is the rough equivalent of find’s {} (the item that was found)

The command I ended up using is below (find any .mdi files and use Microsoft’s mdi2tif utility to convert the result to .tif files)

Get-ChildItem "C:\Users" -Recurse -Filter *.mdi | % { & 'C:\Program
Files (x86)\modiconv\MDI2TIF.EXE' -source $_.FullName -log log.txt }

Clone AD Group Memberships with Powershell

I needed to do windoze administration today.  I dug my way into a hole and finally found my way out. Thanks to answers on Technet for the information I found a way to clone AD group membership from one group to another via powershell.

The command I settled on was the following (after creating the new group first)

Get-ADGroup -Identity "name_of_existing_group" -Properties MemberOf | foreach {$_.MemberOf} | foreach {add-ADGroupMember -Identity $_ -members "new_group_to_copy_memberOf_to" }

It grabs everything the group is a member of and transforms the output to a string array. It then takes that array and uses each item of it to add your new group as a member to everything the old group is a member of.