Public/Add-AdGroupNesting.ps1


# http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-and-windows-part-1-understanding-privileged-groups-in-ad.aspx
# http://blogs.msmvps.com/acefekay/2012/01/06/using-group-nesting-strategy-ad-best-practices-for-group-strategy/
function Add-AdGroupNesting {
    <#
        .SYNOPSIS
            Same as Add-AdGroupMember but with error handling and loging
        .DESCRIPTION
            Same as Add-AdGroupMember but with error handling and loging
        .EXAMPLE
            Add-AdGroupNesting -Identity "Domain Admins" -Members TheUgly
        .NOTES
            Version: 1.0
            DateModified: 22/Jun/2016
            LasModifiedBy: Vicente Rodriguez Eguibar
                vicente@eguibar.com
                Eguibar Information Technology S.L.
                http://www.eguibarit.com
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    Param
    (
        # Param1 Group which membership is to be changed
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $False,
            HelpMessage = 'Group which membership is to be changed',
            Position = 0)]
        [ValidateNotNullOrEmpty()]
        [Alias('GroupName')]
        $Identity,

        # Param2 ID of New Member of the group
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $False,
            HelpMessage = 'ID of New Member of the group. Can be a single string or array.',
            Position = 1)]
        [ValidateNotNullOrEmpty()]
        [Alias('NewMembers')]
        $Members
    )

    Begin {
        Write-Verbose -Message '|=> ************************************************************************ <=|'
        Write-Verbose -Message (Get-Date).ToShortDateString()
        Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand)
        Write-Verbose -Message ('Parameters used by the function... {0}' -f (Set-FunctionDisplay $PsBoundParameters -Verbose:$False))

        if (-not (Get-Module -Name 'ActiveDirectory' -ListAvailable)) {
            Import-Module -Name 'ActiveDirectory' -Force -Verbose:$false
        } #end If

        ##############################
        # Variables Definition

        # Active Directory Domain Distinguished Name
        If (-Not (Test-Path -Path variable:AdDn)) {
            $AdDn = ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString()
        }

        # Define variables and its type
        $CurrentMembers = [System.Collections.Generic.HashSet[String]]::New()
        $NewMembers = [System.Collections.Generic.HashSet[String]]::New()
        $Splat = [hashtable]::New()

        If ($identity -is [Microsoft.ActiveDirectory.Management.AdGroup]) {
            #$Group = Get-AdGroup -Identity $Identity.ObjectGUID
            $Group = $Identity
        }

        If ($identity -is [System.String]) {
            If ($identity -contains $AdDn) {
                $Group = Get-ADGroup -Filter { distinguishedName -eq $Identity }
            }
            ELSE {
                $Group = Get-ADGroup -Filter { samAccountName -eq $Identity }
            }
        }
    }
    Process {
        # Get group members
        Get-ADGroupMember -Identity $Group.SID | Select-Object -ExpandProperty sAMAccountName | ForEach-Object { $CurrentMembers.Add($_) }

        try {
            Write-Verbose -Message ('Adding members to group..: {0}' -f $Group.SamAccountName)

            Foreach ($item in $Members) {
                If ($CurrentMembers -notcontains $item) {
                    $NewMembers.Add($item)
                }
                else {
                    Write-Verbose -Message ('{0} is already member of {1} group' -f $item.SamAccountName, $Group.SamAccountName)
                }
            }
            If ($NewMembers.Count -gt 0) {
                $Splat = @{
                    Identity = $Group
                    Members  = $NewMembers
                }

                If ($PSCmdlet.ShouldProcess("Add members to Group $(Group.SamAccountName)", 'Confirm?')) {
                    Add-ADGroupMember @Splat -WhatIf:$False
                }
                else {
                    Write-Verbose -Message 'Operation cancelled by User!'
                }
            }
            #Add-AdGroupMember @Splat

            Write-Verbose -Message ('Member {0} was added correctly to group {1}' -f $Members, $Group.sAMAccountName)
        }
        catch {
            Get-CurrentErrorToDisplay -CurrentError $error[0]
        }
    }
    End {
        Write-Verbose -Message "Function $($MyInvocation.InvocationName) adding members to the group."
        Write-Verbose -Message ''
        Write-Verbose -Message '--------------------------------------------------------------------------------'
        Write-Verbose -Message ''
    }
}