Author Posts

May 1, 2016 at 3:12 pm

Hello All,
I was wondering how to use PowerShell script export AD group membership of multiple users to CSV or text file than delete them from all groups excluding primary groups. Any help would be greatly appreciated.

I am looking for something that would give me list of all groups User A, than All groups of User B, and so on. If my question unclear please let me know

Thanks,
Kivi

May 27, 2016 at 2:40 pm

Kivi, you'll want to use a couple cmdlets from the Active Directory module. In particular, the Get-ADPrincipalGroupMembership cmdlet is key to getting the groups of which a particular user (or group) is a member.

Since your task is potentially destructive, I would approach it in two parts. First, generate the group membership list, and confirm that you are getting accurate data. Then perform the group membership removal as a subsequent step, which should be reversible if your exported data from the previous step is valid.

Presuming that you have a text file that contains a few usernames (samaccountnames), one per line, something like this might work. Please don't just run this code! It's mean as a place to start. I didn't write a whole script with error handling and warning about the potential to blow away all group membership in your organization.

# Part 1 - Generate a CSV file first, with format like:
# "userX","CN=Example User,CN=Users,DC=contoso,DC=com","Accounting","CN=Accounting,CN=Users,DC=contoso,DC=com","FALSE"

Get-Content -path 'C:\temp\UserList.txt' | foreach {

    $User   = Get-ADUser $_ -Properties PrimaryGroup
    $Groups = Get-ADPrincipalGroupMembership $User

    Foreach ($group in $Groups) {
        $Props = @{
	        UserID  = $User.SAMAccountName
	        UserDN  = $User.DistinguishedName
	        GroupID = $group.SamAccountName
	        GroupDN = $group.DistinguishedName
	        IsUserPrimaryGroup = ( $group.DistinguishedName -eq $User.PrimaryGroup )
        }

        # One CSV line for each user/group 
        New-Object PSObject -Property $Props
    }

} | Export-Csv -Path 'C:\temp\UserGroups.csv' -NoTypeInfo


# Part 2 - Remove the users from all but the Primary Group (and Domain Users)
Import-Csv C:\temp\UserGroups.csv | Where IsUserPrimaryGroup -eq $false | 
    Where GroupID -ne 'Domain Users' | Foreach {
        Write-Verbose "Removing '$($_.UserID)' from '$($_.GroupID)'"
        Remove-ADGroupMember $_.GroupDN -Members $_.UserDN -confirm:$false
    }

If you have many users to process, there are ways to optimize the code to prevent having to make a call for each group removal. you can Remove a list of groups from a single user, or a list of users from a single group, as one operation.

I hope that's helpful.

May 31, 2016 at 11:49 pm

I wrote this function for myself because I do this at work quite often. This function is only good for a single user, but can easily be modified to accept multiple strings in the parameter.

Function Get-ADUMemberOf{
< #
.SYNOPSIS
  Retrieves group membership for target user object

.DESCRIPTION
  Retrieves group membership for a target user object. Has the ability to capture group membership to a list, then attempt to remove all groups
  writing each failed group to $Report2 

.INPUTS
  None

.OUTPUTS
  $Report1 - Log file of existing group memberships stored in C:\scripts\reports\Memberof__Before.txt
  $Report2 - Log file remaining group memberships stored in C:\scripts\reports\MemberOf__After.txt
 
.NOTES
  Version:        2.2
  Author:         Logan "L-Bo" Boydell
  Creation Date:  03/03/2016
  Purpose/Change:

  v2.0 - Put into proper format, changed $Group variable to contain the values from the "SamAccountName" attribute instead of
         the name attribute. This eliminates the "Not Found" issue when the name doesn't match the SamAccountName when using 
         the -remove parameter

  v2.1 - Modified specifically for Transfer Script to integrate with Get-COMPANYADGroupPermission function for added usability
         # Start-Sleep -Seconds 2
         # Start-Process  notepad -ArgumentList "$Report2"

  v2.2 - Used "Set-Variable" cmdlet with "-Scope" parameter, value set to "Script". This creates variables that are available 
         during the execution of the script. ($Report2 is used in the proxy script to generate the final report)

.EXAMPLE
  PS C:\Windows\system32> Get-ADUMemberOf -Identity Billy.User
  DL-TestRestrictGroup
  DL-TestRestrictGroup1

  Outputs group memberships for AD User "Billy.User" to the console
.EXAMPLE
  PS C:\Windows\system32> Get-ADUMemberof -Identity Jesse.Pinkman -Remove

  Creates "MemberOf_'Jesse.Pinkman'_BEFORE.txt", attempts to remove all the
  groups the user is a member of, then creates a "MemberOf_'Jesse.Pinkman'_AFTER.txt"
  for any groups that couldn't be removed
#>

    [CmdletBinding()]
    [OutputType([int])]
    Param
    (
        # Param1 SamAccountName of AD User Object
        [Parameter(Mandatory=$true,
                   HelpMessage="Enter SamAccountName of User Object",
                   Position=0)]
        [string]$Identity,[switch]$Remove)

    Begin
    {

     Set-Variable -Name "Path" -Value "C:\scripts\reports" -Scope Script
     Set-Variable -Name "Before" -Value "MemberOf_'$Identity'_BEFORE.txt" -Scope Script
     Set-Variable -Name "After" -Value "MemberOf_'$Identity'_AFTER.txt" -Scope Script
     Set-Variable -Name "Report1" -Value (Join-Path -Path $Path -ChildPath $Before) -Scope Script
     Set-Variable -Name "Report2" -Value (Join-Path -Path $Path -ChildPath $After) -Scope Script

     $DC = Get-ADDomainController | Select-Object -ExpandProperty HostName
     #Set-Variable -Name "DC" -Value (Get-ADDomainController | select -ExpandProperty HostName) -Scope Script

    }

    Process
    {
     Foreach($I in $Identity)
        {
         $User = @()
         $Group = @()
    
         $User = Get-ADUser -Identity $I -Properties MemberOf -Server $DC
         $Group  = $User.Memberof | Get-ADGroup -Server $DC| Select-Object -ExpandProperty  samaccountname | Sort-Object
        }
    
     If($Remove)
         { 
            If($Group -eq  $null) {Write-Warning "There are no group memberships to remove from $($User.name)"}
            Else # Export list of groups before any actions are taken
            {
             # Test if $Path exists, else make $Path
             If(Test-Path $Path) {} 
             Else {md $Path *>$null}
    
             # Test if $Report1 exists, else make $Report1
             If(Test-Path $Report1) {Write-Verbose "$Report1 already exists! The existing file is unchanged"}
             Else {
                    Write-Host "Creating " -NoNewline;  Write-Host "$Report1" -F Yellow
                    $Group | Out-File $Report1
                  }

                Foreach($G in $Group)
                    {
                        Remove-ADGroupMember -Identity $G -Members $I -Server $DC -Confirm:$false -ErrorAction Stop
    
                           # Traps terminating errors and writes the group names to $Report2
                         Trap [Microsoft.ActiveDirectory.Management.ADException] 
                           {Write-Verbose "Insufficient rights over ""$G"", saving to list..."
                            #$G | Export-Csv -Path $Report2 -NoTypeInformation -Append; continue
                            $G | Out-File $Report2 -Append; continue
                           }
                        
                         Trap [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] 
                           {Write-Verbose "Cannot find a group with identity: ""$G"", saving to list..."
                            #$G | Export-Csv $Report2 -NoTypeInformation -Append; continue
                            $G | Out-File $Report2 -Append; continue
                           }
                    }
            }
         }
    }
    
    End
    {
        If($Remove)
         {
            If(Test-Path $Report2) 
             {
              Write-Warning "GROUP MEMBERSHIPS REMAIN!!!"
              Write-Verbose "Assign Remedy tickets for remaining groups based on the generated report"
              #Start-Sleep -Seconds 2
              #Start-Process  notepad -ArgumentList "$Report2"
             }

            $Check = $User.Memberof | Get-ADGroup -Server $DC| Select-Object -ExpandProperty  samaccountname | Sort-Object
            If(!$Remove -and $Check -eq $null) 
            {Write-Warning "$($user.name) doesn't belong to any groups"} 
            Else {}
           }
        Else{$Group}
          
    }
}
  • This reply was modified 2 years, 2 months ago by  L-Bo.
  • This reply was modified 2 years, 2 months ago by  L-Bo.