Public/Invoke-ADGrouper.ps1

Function Invoke-ADGrouper {
    <#
    .SYNOPSIS
        Adjust AD group membership based on yaml config files
 
    .DESCRIPTION
        Adjust AD group membership based on yaml config files
 
        YAML schema:
 
        'Target Group': # Target security group we are populating
          Purge: # Whether to remove existing accounts in the groupthat aren't included in this definition. Defaults to false
          Recurse: # Whether to recurse membership when source is a group. Defaults to true
          Expand: # Whether to expand to individual accounts within the group, or use the group explicitly. Defaults to true
          Exclude: # Accounts to exclude from this group
            BadUser: # Exclude account
            BadGroup: # Exclude account with overriden Recurse
              - Recurse: False
          ExcludeQuery: # One or more LDAP queries whose resulting accounts are excluded from the target group
            - '(b=a)'
          Include: # Accounts to include in this group
            GoodGroup: # Include account with global settings
            GoodGroup2: # Include account with overriden Expand and Recurse
            - Expand: False
            - Recurse: False
          IncludeQuery: # One or more LDAP queries whose resulting accounts are included in the target group
            - '(a=b)'
            - '(c=d)'
 
    .FUNCTIONALITY
        Active Directory
 
    .PARAMETER InputObject
        Yaml dynamic group definition
 
    .PARAMETER Path
        Path to yaml containing dynamic group definition
 
    .EXAMPLE
        Invoke-ADGrouper $Yaml -Whatif
 
        # See what Invoke-ADGrouper would do with yaml, without doing it
 
    .Example
        Invoke-ADGrouper -Path \\Path\To\example.yaml -Confirm:$False -Force
 
        # Run example.yaml through Invoke-ADGrouper without confirmation
 
    .LINK
        Get-ADDynamicGroup
 
    .LINK
        Expand-ADDynamicGroup
 
    .LINK
        about_ADGrouper
    #>

    [cmdletbinding( DefaultParameterSetName = 'yaml',
                    SupportsShouldProcess=$True,
                    ConfirmImpact='High')]
    param(
        [parameter(ParameterSetName = 'yaml',
                   ValueFromPipeline = $True)]
        [string]$InputObject,

        [parameter(ParameterSetName = 'file',
                   ValueFromPipelineByPropertyName = $True)]
        [Alias('FullName')]
        [string[]]$Path,

        [switch]$Force
    )
    begin
    {
        $RejectAll = $false
        $ConfirmAll = $false
    }
    process
    {
        $ToProcess = [System.Collections.ArrayList]@()
        if($PSCmdlet.ParameterSetName -eq 'file')
        {
            foreach($File in $Path)
            {
                $ToProcess.AddRange( @(Get-Content $File -Raw) )
            }
        }
        else
        {
            [void]$ToProcess.Add($InputObject)
        }
        Write-Verbose ($ToProcess | Out-String)
        $ToExpand = $ToProcess | Get-ADDynamicGroup
        $ToChange = Expand-ADDynamicGroup -InputObject $ToExpand
        foreach($Change in $ToChange)
        {
            $Todo = "[{0}] [{1}] to/from [{2}]" -f $Change.Action, $Change.Account, $Change.Group
            if($PSCmdlet.ShouldProcess( "Group changed '$Todo'",  "Group change '$Todo'?", "Changing group membership" ))
            {    
                if($Force -or $PSCmdlet.ShouldContinue("Are you REALLY sure you want to change '$Todo'?", "Removing '$Todo'", [ref]$ConfirmAll, [ref]$RejectAll))
                {
                    switch ($Change.Action)
                    {
                        'Add' {
                            Add-ADGroupMember -Identity $Change.Group -Members $Change.Account
                        }
                        'Remove' {
                            Remove-ADGroupMember -Identity $Change.Group -Members $Change.Account
                        }
                    }
                }
            }
        }
    }
}