locked
Powershell Script ad or remove user into a new group according to their group RRS feed

  • Question

  • Hi,

    I've done this script because I want it to search every $user in $users who are in a specific group (group1) and if they are, ad them into another group(group2). I want that if I delete one of them in group1 it will be remove in group2 too but not the opposite. I hope you understand me (sry for my bad english).

    My script doesn't work I've got this error :

    Get-ADUser : Cannot validate argument on parameter "identity". the argument is null or a null element of the argument collection contains a null value.
    Au caractère C:\Users\lsoriano\Documents\compare group.ps1:13 : 21
    +     If ((Get-ADUser $user.PrincipalName -Properties MemberOf).MemberO ...
    +                     ~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidData : (:) [Get-ADUser], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.Ge 
       tADUser


    Import-Module ActiveDirectory

    # Group1
    $Source_Group = "CN=Group1,OU=Groups,OU=Leadformance,DC=leadformance,DC=local" 

    # GRoup2
    $Destination_Group = "CN=Group2,OU=Groups,OU=Leadformance,DC=leadformance,DC=local"

    $users = "OU=Users,OU=Leadformance,DC=leadformance,DC=local"

    Foreach ($user In $users)
    {
        If ((Get-ADUser $user.SamAccountName -Properties MemberOf).MemberOf -Contains $Source_Group)
            {
          
                Add-ADGroupMember -Identity $Destination_Group -Members $User.SamAccountName
            }
            Else 
            {
                Remove-ADGroupMember -Identity $Destination_Group -Members $User.SamAccountName
            }
    }


    Monday, March 11, 2019 3:04 PM

Answers

  • Hello,

    I created a function base on your requirements. Sync-ADGroup will look at both group members and will make DestinationGroup a mirror to SourceGroup.

    Additional Features:

    -Test SourceGroup - if exists, if the function is unable to find SourceGroup Break.

    -Test DestinationGroup - if unable to find DestinationGroup create DestinationGroup in the same OU as SourceGroup.

    -MODE Options: ADD, REMOVE, SYNC, TEST

       -ADD Add users only

        -REMOVE Remove users only

        -SYNC Add and Remove users

        -TEST Display Add and Remove users (No actions are taken, display only)


    Function Sync-ADGroup{
    <#
    .SYNOPSIS
        Compare two Active Directory security groups. Look at each groups members to SYNC, ADD, REMOVE, TEST.
    
    .DESCRIPTION
        Sync-ADGroup looks at your $SourceGroup security group members and compares them to $DestinationGroup security group members. MODE sets what happens.
    
        The function has some error checking if the function is unable to find $SourceGroup code Break. If $DestinationGroup is not available, create $DestinationGroup security group in the same OU as $SourceGroup
    
    .LINK
        https://www.cit-devops.com
    
    .NOTES
        Created By Ronnie Rosal
        Version 1
    
    .PARAMETER KEY
        -SourceGroup <String> 
            Soruce Security group with the users you want to SYNC, ADD, REMOVE, TEST
        
        -DestinationGroup <String>
            Destination Security group that will SYNC, ADD, REMOVE, TEST from Source Security group
        -Mode <String>
            Mode Options: ADD, REMOVE, SYNC, TEST
                ADD - Add users only
                REMOVE - Remove users only
                SYNC - Add and Remove users
                TEST - Display Add and Remove users (No actions will be ran)
    
    .EXAMPLE
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode SYNC
    test-help was not detected, creating security group
    Adding qtrinidad to test-help
    Adding alowe to test-help
    Adding freid to test-help
    Adding nedwards to test-help
    Adding afigueroa to test-help
    Adding pguzman to test-help
    Adding bmilner to test-help
    Adding whutchison to test-help
    Adding sjohnson to test-help
    Adding pbaird to test-help
    End of Sync-ADGroup for test-help run
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode TEST
    TESTING MODE-Adding qtrinidad to test-help
    TESTING MODE-Adding alowe to test-help
    TESTING MODE-Adding freid to test-help
    TESTING MODE-Adding nedwards to test-help
    TESTING MODE-Adding afigueroa to test-help
    TESTING MODE-Adding pguzman to test-help
    TESTING MODE-Adding bmilner to test-help
    TESTING MODE-Adding whutchison to test-help
    TESTING MODE-Adding sjohnson to test-help
    TESTING MODE-Adding pbaird to test-help
    End of Sync-ADGroup for test-help run
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode SYNC
    No new members to add to test-help
    Removing ckelly from test-help
    Removing breno from test-help
    Removing cwilt from test-help
    End of Sync-ADGroup for test-help run
    #>
    [CmdletBinding()]
    Param (
        [Parameter(Position = 0,Mandatory = $True)]
        $SourceGroup,
        [Parameter(Position = 0,Mandatory = $True)]
        $DestinationGroup,
        [Parameter(Position = 0,Mandatory = $False)]
        [ValidateSet("ADD","REMOVE","SYNC","TEST")]
        $Mode = "SYNC")
    
    Import-Module ActiveDirectory
    
    $AllADGroups = Get-ADGroup -Filter *
    
    If(($AllADGroups | where {$_.SamAccountName -eq $SourceGroup}) -eq $NULL){
        Write-Warning "Warning Script Break - Unable to find security group $($SourceGroup)"
        Break
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $SourceGroup}) -ne $NULL){
        $SourceGroupProperties = $AllADGroups | where {$_.SamAccountName -eq $SourceGroup}
        $SourceGroupOU = $SourceGroupProperties.DistinguishedName -replace "CN=$($SourceGroupProperties.Name),"
        $SourceGroupMembers = $(Get-ADGroupMember -Identity $SourceGroup)
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $DestinationGroup}) -eq $NULL){
        New-ADGroup -Name $DestinationGroup -SamAccountName $DestinationGroup -GroupCategory Security -GroupScope Global -DisplayName $DestinationGroup -Path $SourceGroupOU
        Write-Host "$($DestinationGroup) was not detected, creating security group"
        Start-Sleep 10
        $DestinationGroupMembers = $(Get-ADGroupMember -Identity $DestinationGroup)
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $DestinationGroup}) -ne $NULL){
        $DestinationGroupMembers = $(Get-ADGroupMember -Identity $DestinationGroup)
    }
    
    If($DestinationGroupMembers -eq $NULL){
        $DestinationGroupMembersSamaccountname = 'NULL'
    }Else{
        $DestinationGroupMembersSamaccountname = $DestinationGroupMembers.SamAccountName
    }
    
    $UsersToAdd = Compare-Object $SourceGroupMembers.SamAccountName $DestinationGroupMembersSamaccountname | where {$_.SideIndicator -eq "<="}
    $UsersToAddInputObject = $UsersToAdd.InputObject
    
    $UsersToRemove = Compare-Object $SourceGroupMembers.SamAccountName $DestinationGroupMembersSamaccountname | where {$_.SideIndicator -eq "=>"}
    $UsersToRemoveInputObject = $UsersToRemove.InputObject
    
    If($Mode -eq "ADD" -or $Mode -eq "SYNC"){
        If($UsersToAddInputObject -ne $NULL){
            If($UsersToAddInputObject -ne "NULL"){
                ForEach($MembersToAdd in $UsersToAddInputObject){
                    Add-ADGroupMember -Identity $DestinationGroup -Members $MembersToAdd
                    Write-Host "Adding $MembersToAdd to $DestinationGroup" -foregroundcolor "Green"
                }
            }
        }
        If($UsersToAddInputObject -eq $NULL){
            Write-Host "No new members to add to $DestinationGroup" -foregroundcolor "Yellow"
        }
    }
    
    If($Mode -eq "REMOVE" -or $Mode -eq "SYNC"){
        If($UsersToRemoveInputObject -ne $NULL){
            If($UsersToRemoveInputObject -ne "NULL"){
                ForEach($MembersToRemove in $UsersToRemoveInputObject){
                    Remove-ADGroupMember -Identity $DestinationGroup -Members $MembersToRemove -Confirm:$false
                    Write-Host "Removing $MembersToRemove from $DestinationGroup" -foregroundcolor "Red"
                }
            }
        }
        If($UsersToRemoveInputObject -eq $NULL){
            Write-Host "No new members to remove from $DestinationGroup" -foregroundcolor "Red"
        }
    }
    
    If($Mode -eq "TEST"){
        If($UsersToAddInputObject -ne $NULL){
            If($UsersToAddInputObject -ne "NULL"){
                ForEach($MembersToAdd in $UsersToAddInputObject){
                    Write-Host "TESTING MODE-Adding $MembersToAdd to $DestinationGroup" -foregroundcolor "Green"
                }
            }
        }
        If($UsersToAddInputObject -eq $NULL){
            Write-Host "TESTING MODE-No new members to add to $DestinationGroup" -foregroundcolor "Yellow"
        }
        If($UsersToRemoveInputObject -ne $NULL){
            If($UsersToRemoveInputObject -ne "NULL"){
                ForEach($MembersToRemove in $UsersToRemoveInputObject){
                    Write-Host "TESTING MODE-Removing $MembersToRemove to $DestinationGroup" -foregroundcolor "Red"
                }
            }
        }
        If($UsersToRemoveInputObject -eq $NULL){
            Write-Host "TESTING MODE-No new members to remove to $DestinationGroup" -foregroundcolor "Yellow"
        }
    }
    
    Write-Host "End of Sync-ADGroup for $($DestinationGroup) run"
    }

    I hope this fulfills what you are trying to accomplish.

    This seems like a good topic to cover in my blog (www.cit-devops.com), I will write about it in the next few days in detail.

    Cheers!

    Ronnie

    • Proposed as answer by CITLead Monday, March 11, 2019 6:21 PM
    • Marked as answer by Nightingal Tuesday, March 12, 2019 9:30 AM
    Monday, March 11, 2019 5:36 PM

All replies

  • You could make one group a member of the other (nested groups). Then when you modify the membership of the nested group, the membership of the parent group is automatically updated. Permissions granted to the parent group apply to all members recursively, including members of any nested groups.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Monday, March 11, 2019 3:16 PM
  • Thanks for your answer

    I need this operation to be automatic so that's why i create a script that I will put on a planned task.

    Monday, March 11, 2019 3:48 PM
  • Hello,

    I created a function base on your requirements. Sync-ADGroup will look at both group members and will make DestinationGroup a mirror to SourceGroup.

    Additional Features:

    -Test SourceGroup - if exists, if the function is unable to find SourceGroup Break.

    -Test DestinationGroup - if unable to find DestinationGroup create DestinationGroup in the same OU as SourceGroup.

    -MODE Options: ADD, REMOVE, SYNC, TEST

       -ADD Add users only

        -REMOVE Remove users only

        -SYNC Add and Remove users

        -TEST Display Add and Remove users (No actions are taken, display only)


    Function Sync-ADGroup{
    <#
    .SYNOPSIS
        Compare two Active Directory security groups. Look at each groups members to SYNC, ADD, REMOVE, TEST.
    
    .DESCRIPTION
        Sync-ADGroup looks at your $SourceGroup security group members and compares them to $DestinationGroup security group members. MODE sets what happens.
    
        The function has some error checking if the function is unable to find $SourceGroup code Break. If $DestinationGroup is not available, create $DestinationGroup security group in the same OU as $SourceGroup
    
    .LINK
        https://www.cit-devops.com
    
    .NOTES
        Created By Ronnie Rosal
        Version 1
    
    .PARAMETER KEY
        -SourceGroup <String> 
            Soruce Security group with the users you want to SYNC, ADD, REMOVE, TEST
        
        -DestinationGroup <String>
            Destination Security group that will SYNC, ADD, REMOVE, TEST from Source Security group
        -Mode <String>
            Mode Options: ADD, REMOVE, SYNC, TEST
                ADD - Add users only
                REMOVE - Remove users only
                SYNC - Add and Remove users
                TEST - Display Add and Remove users (No actions will be ran)
    
    .EXAMPLE
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode SYNC
    test-help was not detected, creating security group
    Adding qtrinidad to test-help
    Adding alowe to test-help
    Adding freid to test-help
    Adding nedwards to test-help
    Adding afigueroa to test-help
    Adding pguzman to test-help
    Adding bmilner to test-help
    Adding whutchison to test-help
    Adding sjohnson to test-help
    Adding pbaird to test-help
    End of Sync-ADGroup for test-help run
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode TEST
    TESTING MODE-Adding qtrinidad to test-help
    TESTING MODE-Adding alowe to test-help
    TESTING MODE-Adding freid to test-help
    TESTING MODE-Adding nedwards to test-help
    TESTING MODE-Adding afigueroa to test-help
    TESTING MODE-Adding pguzman to test-help
    TESTING MODE-Adding bmilner to test-help
    TESTING MODE-Adding whutchison to test-help
    TESTING MODE-Adding sjohnson to test-help
    TESTING MODE-Adding pbaird to test-help
    End of Sync-ADGroup for test-help run
    
    PS C:\Windows\system32> Sync-ADGroup -SourceGroup "test-staff" -DestinationGroup "test-help" -mode SYNC
    No new members to add to test-help
    Removing ckelly from test-help
    Removing breno from test-help
    Removing cwilt from test-help
    End of Sync-ADGroup for test-help run
    #>
    [CmdletBinding()]
    Param (
        [Parameter(Position = 0,Mandatory = $True)]
        $SourceGroup,
        [Parameter(Position = 0,Mandatory = $True)]
        $DestinationGroup,
        [Parameter(Position = 0,Mandatory = $False)]
        [ValidateSet("ADD","REMOVE","SYNC","TEST")]
        $Mode = "SYNC")
    
    Import-Module ActiveDirectory
    
    $AllADGroups = Get-ADGroup -Filter *
    
    If(($AllADGroups | where {$_.SamAccountName -eq $SourceGroup}) -eq $NULL){
        Write-Warning "Warning Script Break - Unable to find security group $($SourceGroup)"
        Break
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $SourceGroup}) -ne $NULL){
        $SourceGroupProperties = $AllADGroups | where {$_.SamAccountName -eq $SourceGroup}
        $SourceGroupOU = $SourceGroupProperties.DistinguishedName -replace "CN=$($SourceGroupProperties.Name),"
        $SourceGroupMembers = $(Get-ADGroupMember -Identity $SourceGroup)
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $DestinationGroup}) -eq $NULL){
        New-ADGroup -Name $DestinationGroup -SamAccountName $DestinationGroup -GroupCategory Security -GroupScope Global -DisplayName $DestinationGroup -Path $SourceGroupOU
        Write-Host "$($DestinationGroup) was not detected, creating security group"
        Start-Sleep 10
        $DestinationGroupMembers = $(Get-ADGroupMember -Identity $DestinationGroup)
    }
    
    If(($AllADGroups | where {$_.SamAccountName -eq $DestinationGroup}) -ne $NULL){
        $DestinationGroupMembers = $(Get-ADGroupMember -Identity $DestinationGroup)
    }
    
    If($DestinationGroupMembers -eq $NULL){
        $DestinationGroupMembersSamaccountname = 'NULL'
    }Else{
        $DestinationGroupMembersSamaccountname = $DestinationGroupMembers.SamAccountName
    }
    
    $UsersToAdd = Compare-Object $SourceGroupMembers.SamAccountName $DestinationGroupMembersSamaccountname | where {$_.SideIndicator -eq "<="}
    $UsersToAddInputObject = $UsersToAdd.InputObject
    
    $UsersToRemove = Compare-Object $SourceGroupMembers.SamAccountName $DestinationGroupMembersSamaccountname | where {$_.SideIndicator -eq "=>"}
    $UsersToRemoveInputObject = $UsersToRemove.InputObject
    
    If($Mode -eq "ADD" -or $Mode -eq "SYNC"){
        If($UsersToAddInputObject -ne $NULL){
            If($UsersToAddInputObject -ne "NULL"){
                ForEach($MembersToAdd in $UsersToAddInputObject){
                    Add-ADGroupMember -Identity $DestinationGroup -Members $MembersToAdd
                    Write-Host "Adding $MembersToAdd to $DestinationGroup" -foregroundcolor "Green"
                }
            }
        }
        If($UsersToAddInputObject -eq $NULL){
            Write-Host "No new members to add to $DestinationGroup" -foregroundcolor "Yellow"
        }
    }
    
    If($Mode -eq "REMOVE" -or $Mode -eq "SYNC"){
        If($UsersToRemoveInputObject -ne $NULL){
            If($UsersToRemoveInputObject -ne "NULL"){
                ForEach($MembersToRemove in $UsersToRemoveInputObject){
                    Remove-ADGroupMember -Identity $DestinationGroup -Members $MembersToRemove -Confirm:$false
                    Write-Host "Removing $MembersToRemove from $DestinationGroup" -foregroundcolor "Red"
                }
            }
        }
        If($UsersToRemoveInputObject -eq $NULL){
            Write-Host "No new members to remove from $DestinationGroup" -foregroundcolor "Red"
        }
    }
    
    If($Mode -eq "TEST"){
        If($UsersToAddInputObject -ne $NULL){
            If($UsersToAddInputObject -ne "NULL"){
                ForEach($MembersToAdd in $UsersToAddInputObject){
                    Write-Host "TESTING MODE-Adding $MembersToAdd to $DestinationGroup" -foregroundcolor "Green"
                }
            }
        }
        If($UsersToAddInputObject -eq $NULL){
            Write-Host "TESTING MODE-No new members to add to $DestinationGroup" -foregroundcolor "Yellow"
        }
        If($UsersToRemoveInputObject -ne $NULL){
            If($UsersToRemoveInputObject -ne "NULL"){
                ForEach($MembersToRemove in $UsersToRemoveInputObject){
                    Write-Host "TESTING MODE-Removing $MembersToRemove to $DestinationGroup" -foregroundcolor "Red"
                }
            }
        }
        If($UsersToRemoveInputObject -eq $NULL){
            Write-Host "TESTING MODE-No new members to remove to $DestinationGroup" -foregroundcolor "Yellow"
        }
    }
    
    Write-Host "End of Sync-ADGroup for $($DestinationGroup) run"
    }

    I hope this fulfills what you are trying to accomplish.

    This seems like a good topic to cover in my blog (www.cit-devops.com), I will write about it in the next few days in detail.

    Cheers!

    Ronnie

    • Proposed as answer by CITLead Monday, March 11, 2019 6:21 PM
    • Marked as answer by Nightingal Tuesday, March 12, 2019 9:30 AM
    Monday, March 11, 2019 5:36 PM
  • Wow that seems very nice, huge thanks for this !!

    I try to use it and that is what my parameters look like 

    [CmdletBinding()]
    Param (
        [Parameter(Position = 0,Mandatory = $True)]
        $SourceGroup = "CHY", 
        [Parameter(Position = 0,Mandatory = $True)]
        $DestinationGroup = "Miroirtest",
        [Parameter(Position = 0,Mandatory = $False)]
        [ValidateSet("ADD","REMOVE","SYNC","TEST")]
        $Mode = "TEST")

    the group "CHY" and "Miroirtest" are in the same OU, CHY as a lot of members and Miroirtest nothing, but nothing is happening when I run the script 

     

    PS C:\Windows\system32> C:\Users\lsoriano\Documents\SyncAdGroup.ps1

    PS C:\Windows\system32> 

    0 error but nothing is happening ;-( any idea ?

    Thanks again for your time !!!

    Tuesday, March 12, 2019 9:03 AM
  • My bad I checked on your site and see the exemple in video now I understand and it work perfectly !!! Thank you very much !!
    Tuesday, March 12, 2019 9:30 AM
  • No problem, visit my site in a few weeks I have a few ideas on how to improve the code. I want to test out a few things before I post anything. Just a hint, I want to expand on the idea to help manage distribution lists or distribution list manage security groups.
    Tuesday, March 12, 2019 3:16 PM