Manage ActiveDirectory Distribution Groups

With Office365 connected with an ADFS you have to redesgin your Exchange distribution groups. ADFS only syncs distribution groups that have these definitions:

  • Group scope is universal
  • Group type is distribution
  • Group members have to be users
    • Yes, it’s not possible to have security groups or something else as distribution group members.

My idea was simple, I’m developing a script that creates for every OU and child OU I’m chosing in the ActiveDirectory structure a distribution list containing the users of the chosen OU recursively.

While developing this I’ve added some cool features, in addition you can:

  • Copy the members of one or more groups into another.
  • Remove the members of one or more group in an another group.
  • Exclude users in distribution groups.
  • Exclude distribution groups.

By default the script will only add enabled users with an email address.

This script makes use of the PowerShell Profile environment, f.e. the function Send-PPErrorReport sends an error report per email when the script fails or produces problems.

<#
$Metadata = @{
    Title = "New ActiveDirectory Distribution Groups"
    Filename = "New-ADDistributionGroups.ps1"
    Description = "Create or update ActiveDirectory distribution groups"
    Tags = "powershell, activedirectory, distribution, groups, create, update"
    Project = ""
    Author = "Janik von Rotz"
    AuthorContact = "https://janikvonrotz.ch"
    CreateDate = "2013-08-27"
    LastEditDate = "2013-09-30"
    Url = "https://gist.github.com/6352037"
    Version = "1.1.0"
    License = @'
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Switzerland License.
To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/3.0/ch/ or
send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
'@
}
#>

#--------------------------------------------------#
# modules
#--------------------------------------------------#
Import-Module ActiveDirectory

# set OUs where the distributions groups should be enabled
$OUs = @(
    @{Name = "OU=Betrieb,OU=vblusers2,DC=vbl,DC=ch"},
    @{Name = "OU=Direktion,OU=vblusers2,DC=vbl,DC=ch"},
    @{Name = "OU=Finanzen,OU=vblusers2,DC=vbl,DC=ch"},
    @{Name = "OU=Personal,OU=vblusers2,DC=vbl,DC=ch"},
    @{Name = "OU=Technik,OU=vblusers2,DC=vbl,DC=ch"}
)

# list of users to exclude in distribution groups
$ExcludeUsers = "abascan","ba test","ba-service"

# list of distribution groups to exclude
$ExcludeOUs = "Verwaltungsrat"

# special configuration to handle special
$Configs = @(
    @{
        Name = "GL";
        Options = @("UpdateFromGroups");
        AddGroups = @("Geschäftsleitung Gruppe")
    },
    @{
        Name = "GL erw";
        Options = @("UpdateFromGroups");
        AddGroups = @("Erweiterte Geschäftsleitung Gruppe")
    },
    @{
        Name = "Alle";
        Options = @("UpdateFromGroups");
        AddGroups = @("Technik","Betrieb","Personal","Finanzen","GL","Kommunikation","Sekretariat")
    },
    @{
        Name = "Alle mit Arbeitsplatz";
        Options = @("UpdateFromGroups","RemoveGroups");
        AddGroups = @("Alle");
        RemoveGroups = @("SPO_365E1License")
    },
    @{
        Name = "Alle ohne Arbeitsplatz";
        Options = @("UpdateFromGroups");
        AddGroups = @("SPO_365E1License");
    },
    @{
        Name = "Fahrdienst A - Hermann M";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst A - Hermann M Gruppe");
    },
    @{
        Name = "Fahrdienst A - Segui M";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst A - Segui M Gruppe");
    },
    @{
        Name = "Fahrdienst B - Nietlispach M";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst B - Nietlispach M Gruppe");
    },
    @{
        Name = "Fahrdienst B - Zaugg D";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst B - Zaugg D Gruppe");
    },
    @{
        Name = "Fahrdienst C - Habegger R";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst C - Habegger R Gruppe");
    },
    @{
        Name = "Fahrdienst C - Malbasic N";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst C - Malbasic N Gruppe");
    },
    @{
        Name = "Fahrdienst D - Küchler P";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst D - Küchler P Gruppe");
    },
    @{
        Name = "Fahrdienst D - Zimmermann L";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst D - Zimmermann L Gruppe");
    },
    @{
        Name = "Fahrdienst E - Bechter K";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst E - Bechter K Gruppe");
    },
    @{
        Name = "Fahrdienst E - Brunner R";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst E - Brunner R Gruppe");
    },
    @{
        Name = "Fahrdienst F - Bieri René";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst F - Bieri René Gruppe");
    },
    @{
        Name = "Fahrdienst F - Bieri Urs";
        Options = @("UpdateFromGroups");
        AddGroups = @("Fahrdienst F - Bieri Urs Gruppe");
    },
    @{
        Name = "Verkehrsdisponnenten";
        Options = @("UpdateFromGroups");
        AddGroups = @("F_Verkehrsdisponnenten");
    },
    @{
        Name = "Personalkommission";
        Options = @("UpdateFromGroups");
        AddGroups = @("Personalkommission Abteilung");
    }
)

# get all OUs recursive
$OUs = $OUs | %{Get-ADOrganizationalUnit -Filter "*" -SearchBase $_.Name} | where {-not ($ExcludeOUs -contains $_.Name)}

# check in every OU if a distribution group with the same name as the OU exist
$OUs | %{$OU = $_.DistinguishedName;
    if(Get-ADGroup -Filter {SamAccountName -eq $_.Name -and GroupCategory -eq "Distribution"} | Where-Object{$_.DistinguishedName -like "*$OU"}){

        Write-Host "Update users in distribution group $($_.Name)."
        $ADGroup = Get-ADGroup -Filter {SamAccountName -eq $_.Name -and GroupCategory -eq "Distribution"}
        Get-ADGroupMember -Identity $ADGroup | %{Remove-ADGroupMember -Identity $ADGroup -Members $_ -Confirm:$false}
        Get-ADUser -Filter {EmailAddress -like "*"} -SearchBase $OU | where {$_.enabled -eq $true -and -not ($ExcludeUsers -contains $_.Name)} | where{$_ -ne $null} | %{Add-ADGroupMember -Identity $ADGroup -Members $_}

    }else{

        Write-Host "Create distribution group $($_.Name)."
        New-ADGroup -Name $_.Name -SamAccountName $_.Name -GroupCategory Distribution -GroupScope Universal -DisplayName $_.Name -Path $($_.DistinguishedName) -Description "Distribution group for $($_.Name)."
        $ADGroup = Get-ADGroup $_.Name
        Get-ADUser -Filter {EmailAddress -like "*"} -SearchBase $_.DistinguishedName | where {$_.enabled -eq $true -and -not ($ExcludeUsers -contains $_.Name)} | where{$_ -ne $null} | %{Add-ADGroupMember -Identity $ADGroup -Members $_}
    }
}

# custom configuration
$Configs | %{

    $ADGroup = Get-ADGroup -Identity $_.Name
    $Config = $_

    if($_.Options -match "UpdateFromGroups"){

        Write-Host "Add users from $($Config.AddGroups) to $($ADGroup.Name)."
        Get-ADGroupMember -Identity $ADGroup | %{Remove-ADGroupMember -Identity $ADGroup -Members $_ -Confirm:$false}
        $Config.AddGroups | %{Get-ADGroupMember -Identity $_ -Recursive | Get-ADUser | where {($_.enabled -eq $true) -and -not ($ExcludeUsers -contains $_.Name)}} | select -Unique | %{Add-ADGroupMember -Identity $ADGroup -Members $_}

    }

    if($_.Options -match "RemoveGroups"){

        Write-Host "Remove users from $($Config.RemoveGroups) in $($ADGroup.Name)."
        $ADGroupMembers = Get-ADGroupMember -Identity $ADGroup
        $Config.RemoveGroups | %{Get-ADGroupMember -Identity $_ -Recursive | Get-ADUser | where {($ADGroupMembers -match $_) -and ($_.enabled -eq $true) -and -not ($ExcludeUsers -contains $_.Name)}} | select -Unique  | %{Remove-ADGroupMember -Identity $ADGroup -Members $_ -Confirm:$false}

    }
}

if($error){
    Send-PPErrorReport -FileName "activedirectory.mail.config.xml" -ScriptName $MyInvocation.InvocationName
}

Latest version of this script: https://gist.github.com/6352037

Leave a Reply